GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
max.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <cmath>
31 
32 #include "lo-ieee.h"
33 #include "lo-mappers.h"
34 #include "dNDArray.h"
35 #include "CNDArray.h"
36 #include "quit.h"
37 
38 #include "defun.h"
39 #include "error.h"
40 #include "errwarn.h"
41 #include "ovl.h"
42 
43 #include "ov-cx-mat.h"
44 #include "ov-re-sparse.h"
45 #include "ov-cx-sparse.h"
46 
48 
49 template <typename ArrayType>
50 static octave_value_list
51 do_minmax_red_op (const octave_value& arg,
52  int nargout, int dim, bool ismin)
53 {
54  octave_value_list retval (nargout > 1 ? 2 : 1);
55  ArrayType array = octave_value_extract<ArrayType> (arg);
56 
57  if (nargout <= 1)
58  {
59  if (ismin)
60  retval(0) = array.min (dim);
61  else
62  retval(0) = array.max (dim);
63  }
64  else
65  {
67  if (ismin)
68  retval(0) = array.min (idx, dim);
69  else
70  retval(0) = array.max (idx, dim);
71 
72  retval(1) = octave_value (idx, true, true);
73  }
74 
75  return retval;
76 }
77 
78 // Matlab returns double arrays for min/max operations on character
79 // arrays, so we specialize here to get that behavior. Other possible
80 // solutions are to convert the argument to double here and call the
81 // code for double, but that could waste memory, or to have the
82 // underlying charNDArray::min/max functions return NDArray instead of
83 // charNDArray, but that is inconsistent with the way other min/max
84 // functions work.
85 
86 template <>
89  int nargout, int dim, bool ismin)
90 {
91  octave_value_list retval (nargout > 1 ? 2 : 1);
93 
94  if (nargout <= 1)
95  {
96  if (ismin)
97  retval(0) = NDArray (array.min (dim));
98  else
99  retval(0) = NDArray (array.max (dim));
100  }
101  else
102  {
104  if (ismin)
105  retval(0) = NDArray (array.min (idx, dim));
106  else
107  retval(0) = NDArray (array.max (idx, dim));
108 
109  retval(1) = octave_value (idx, true, true);
110  }
111 
112  return retval;
113 }
114 
115 // Specialization for bool arrays (dense or sparse).
116 template <>
119  int nargout, int dim, bool ismin)
120 {
121  octave_value_list retval;
122 
123  if (! arg.issparse ())
124  {
125  if (nargout <= 1)
126  {
127  // This case can be handled using any/all.
128  boolNDArray array = arg.bool_array_value ();
129 
130  if (array.isempty ())
131  retval(0) = array;
132  else if (ismin)
133  retval(0) = array.all (dim);
134  else
135  retval(0) = array.any (dim);
136  }
137  else
138  {
139  // any/all don't have indexed versions, so do it via a conversion.
140  retval = do_minmax_red_op<int8NDArray> (arg, nargout, dim, ismin);
141 
142  retval(0) = retval(0).bool_array_value ();
143  }
144  }
145  else
146  {
147  // Sparse: Don't use any/all trick, as full matrix could exceed memory.
148  // Instead, convert to double.
149  retval = do_minmax_red_op<SparseMatrix> (arg, nargout, dim, ismin);
150 
151  retval(0) = retval(0).sparse_bool_matrix_value ();
152  }
153 
154  return retval;
155 }
156 
157 template <typename ArrayType>
158 static octave_value
159 do_minmax_bin_op (const octave_value& argx, const octave_value& argy,
160  bool ismin)
161 {
162  typedef typename ArrayType::element_type ScalarType;
163 
164  octave_value retval;
165 
166  if (argx.is_scalar_type ())
167  {
168  ScalarType x = octave_value_extract<ScalarType> (argx);
169  ArrayType y = octave_value_extract<ArrayType> (argy);
170 
171  if (ismin)
172  retval = min (x, y);
173  else
174  retval = max (x, y);
175  }
176  else if (argy.is_scalar_type ())
177  {
178  ArrayType x = octave_value_extract<ArrayType> (argx);
179  ScalarType y = octave_value_extract<ScalarType> (argy);
180 
181  if (ismin)
182  retval = min (x, y);
183  else
184  retval = max (x, y);
185  }
186  else
187  {
188  ArrayType x = octave_value_extract<ArrayType> (argx);
189  ArrayType y = octave_value_extract<ArrayType> (argy);
190 
191  if (ismin)
192  retval = min (x, y);
193  else
194  retval = max (x, y);
195  }
196 
197  return retval;
198 }
199 
200 // Matlab returns double arrays for min/max operations on character
201 // arrays, so we specialize here to get that behavior. Other possible
202 // solutions are to convert the arguments to double here and call the
203 // code for double, but that could waste a lot of memory, or to have the
204 // underlying charNDArray::min/max functions return NDArray instead of
205 // charNDArray, but that is inconsistent with the way other min/max
206 // functions work.
207 
208 template <>
211  const octave_value& argy, bool ismin)
212 {
213  octave_value retval;
214 
217 
218  if (ismin)
219  {
220  if (x.numel () == 1)
221  retval = NDArray (min (x(0), y));
222  else if (y.numel () == 1)
223  retval = NDArray (min (x, y(0)));
224  else
225  retval = NDArray (min (x, y));
226  }
227  else
228  {
229  if (x.numel () == 1)
230  retval = NDArray (max (x(0), y));
231  else if (y.numel () == 1)
232  retval = NDArray (max (x, y(0)));
233  else
234  retval = NDArray (max (x, y));
235  }
236 
237  return retval;
238 }
239 
240 static octave_value_list
241 do_minmax_body (const octave_value_list& args,
242  int nargout, bool ismin)
243 {
244  int nargin = args.length ();
245 
246  if (nargin < 1 || nargin > 3)
247  print_usage ();
248 
249  octave_value_list retval (nargout > 1 ? 2 : 1);
250 
251  const char *fcn = (ismin ? "min" : "max");
252 
253  if (nargin == 3 || nargin == 1)
254  {
255  octave_value arg = args(0);
256  int dim = -1;
257  if (nargin == 3)
258  {
259  dim = args(2).int_value (true) - 1;
260 
261  if (dim < 0)
262  error ("%s: DIM must be a valid dimension", fcn);
263 
264  if (! args(1).isempty ())
265  warning ("%s: second argument is ignored", fcn);
266  }
267 
268  switch (arg.builtin_type ())
269  {
270  case btyp_double:
271  {
272  if (arg.is_range () && (dim == -1 || dim == 1))
273  {
275  if (range.numel () < 1)
276  {
277  retval(0) = arg;
278  if (nargout > 1)
279  retval(1) = arg;
280  }
281  else if (ismin)
282  {
283  retval(0) = range.min ();
284  if (nargout > 1)
285  retval(1) = static_cast<double>
286  (range.increment () < 0 ? range.numel () : 1);
287  }
288  else
289  {
290  retval(0) = range.max ();
291  if (nargout > 1)
292  retval(1) = static_cast<double>
293  (range.increment () >= 0 ? range.numel ()
294  : 1);
295  }
296  }
297  else if (arg.issparse ())
298  retval = do_minmax_red_op<SparseMatrix> (arg, nargout, dim,
299  ismin);
300  else
301  retval = do_minmax_red_op<NDArray> (arg, nargout, dim, ismin);
302 
303  }
304  break;
305 
306  case btyp_complex:
307  {
308  if (arg.issparse ())
309  retval = do_minmax_red_op<SparseComplexMatrix> (arg, nargout, dim,
310  ismin);
311  else
312  retval = do_minmax_red_op<ComplexNDArray> (arg, nargout, dim,
313  ismin);
314  }
315  break;
316 
317  case btyp_float:
318  retval = do_minmax_red_op<FloatNDArray> (arg, nargout, dim, ismin);
319  break;
320 
321  case btyp_float_complex:
322  retval = do_minmax_red_op<FloatComplexNDArray> (arg, nargout, dim,
323  ismin);
324  break;
325 
326  case btyp_char:
327  retval = do_minmax_red_op<charNDArray> (arg, nargout, dim, ismin);
328  break;
329 
330 #define MAKE_INT_BRANCH(X) \
331  case btyp_ ## X: \
332  retval = do_minmax_red_op<X ## NDArray> (arg, nargout, dim, ismin); \
333  break;
334 
335  MAKE_INT_BRANCH (int8);
336  MAKE_INT_BRANCH (int16);
337  MAKE_INT_BRANCH (int32);
338  MAKE_INT_BRANCH (int64);
339  MAKE_INT_BRANCH (uint8);
340  MAKE_INT_BRANCH (uint16);
341  MAKE_INT_BRANCH (uint32);
342  MAKE_INT_BRANCH (uint64);
343 
344 #undef MAKE_INT_BRANCH
345 
346  case btyp_bool:
347  retval = do_minmax_red_op<boolNDArray> (arg, nargout, dim, ismin);
348  break;
349 
350  default:
351  err_wrong_type_arg (fcn, arg);
352  }
353  }
354  else
355  {
356  octave_value argx = args(0);
357  octave_value argy = args(1);
358  builtin_type_t xtyp = argx.builtin_type ();
359  builtin_type_t ytyp = argy.builtin_type ();
360  builtin_type_t rtyp;
361  if (xtyp == btyp_char && ytyp == btyp_char)
362  rtyp = btyp_char;
363  // FIXME: This is what should happen when boolNDArray has max()
364  // else if (xtyp == btyp_bool && ytyp == btyp_bool)
365  // rtyp = btyp_bool;
366  else
367  rtyp = btyp_mixed_numeric (xtyp, ytyp);
368 
369  switch (rtyp)
370  {
371  case btyp_double:
372  {
373  if ((argx.issparse ()
374  && (argy.issparse () || argy.is_scalar_type ()))
375  || (argy.issparse () && argx.is_scalar_type ()))
376  retval = do_minmax_bin_op<SparseMatrix> (argx, argy, ismin);
377  else
378  retval = do_minmax_bin_op<NDArray> (argx, argy, ismin);
379  }
380  break;
381 
382  case btyp_complex:
383  {
384  if ((argx.issparse ()
385  && (argy.issparse () || argy.is_scalar_type ()))
386  || (argy.issparse () && argx.is_scalar_type ()))
387  retval = do_minmax_bin_op<SparseComplexMatrix> (argx, argy,
388  ismin);
389  else
390  retval = do_minmax_bin_op<ComplexNDArray> (argx, argy, ismin);
391  }
392  break;
393 
394  case btyp_float:
395  retval = do_minmax_bin_op<FloatNDArray> (argx, argy, ismin);
396  break;
397 
398  case btyp_float_complex:
399  retval = do_minmax_bin_op<FloatComplexNDArray> (argx, argy, ismin);
400  break;
401 
402  case btyp_char:
403  retval = do_minmax_bin_op<charNDArray> (argx, argy, ismin);
404  break;
405 
406 #define MAKE_INT_BRANCH(X) \
407  case btyp_ ## X: \
408  retval = do_minmax_bin_op<X ## NDArray> (argx, argy, ismin); \
409  break;
410 
411  MAKE_INT_BRANCH (int8);
412  MAKE_INT_BRANCH (int16);
413  MAKE_INT_BRANCH (int32);
414  MAKE_INT_BRANCH (int64);
415  MAKE_INT_BRANCH (uint8);
416  MAKE_INT_BRANCH (uint16);
417  MAKE_INT_BRANCH (uint32);
418  MAKE_INT_BRANCH (uint64);
419 
420 #undef MAKE_INT_BRANCH
421 
422  // FIXME: This is what should happen when boolNDArray has max()
423  // case btyp_bool:
424  // retval = do_minmax_bin_op<boolNDArray> (argx, argy, ismin);
425  // break;
426 
427  default:
428  error ("%s: cannot compute %s (%s, %s)", fcn, fcn,
429  argx.type_name ().c_str (), argy.type_name ().c_str ());
430  }
431 
432  // FIXME: Delete when boolNDArray has max()
433  if (xtyp == btyp_bool && ytyp == btyp_bool)
434  retval(0) = retval(0).bool_array_value ();
435 
436  }
437 
438  return retval;
439 }
440 
441 DEFUN (min, args, nargout,
442  doc: /* -*- texinfo -*-
443 @deftypefn {} {@var{m} =} min (@var{x})
444 @deftypefnx {} {@var{m} =} min (@var{x}, [], @var{dim})
445 @deftypefnx {} {[@var{m}, @var{im}] =} min (@var{x})
446 @deftypefnx {} {@var{m} =} min (@var{x}, @var{y})
447 Find minimum values in the array @var{x}.
448 
449 For a vector argument, return the minimum value. For a matrix argument,
450 return a row vector with the minimum value of each column. For a
451 multi-dimensional array, @code{min} operates along the first non-singleton
452 dimension.
453 
454 If the optional third argument @var{dim} is present then operate along
455 this dimension. In this case the second argument is ignored and should be
456 set to the empty matrix.
457 
458 For two inputs (@var{x} and @var{y}), return the pairwise minimum according to
459 the rules for @ref{Broadcasting}.
460 
461 Thus,
462 
463 @example
464 min (min (@var{x}))
465 @end example
466 
467 @noindent
468 returns the smallest element of the 2-D matrix @var{x}, and
469 
470 @example
471 @group
472 min (2:5, pi)
473  @result{} 2.0000 3.0000 3.1416 3.1416
474 @end group
475 @end example
476 
477 @noindent
478 compares each element of the range @code{2:5} with @code{pi}, and returns a
479 row vector of the minimum values.
480 
481 For complex arguments, the magnitude of the elements are used for
482 comparison. If the magnitudes are identical, then the results are ordered
483 by phase angle in the range (-pi, pi]. Hence,
484 
485 @example
486 @group
487 min ([-1 i 1 -i])
488  @result{} -i
489 @end group
490 @end example
491 
492 @noindent
493 because all entries have magnitude 1, but -i has the smallest phase angle
494 with value -pi/2.
495 
496 If called with one input and two output arguments, @code{min} also returns
497 the first index of the minimum value(s). Thus,
498 
499 @example
500 @group
501 [x, ix] = min ([1, 3, 0, 2, 0])
502  @result{} x = 0
503  ix = 3
504 @end group
505 @end example
506 @seealso{max, cummin, cummax}
507 @end deftypefn */)
508 {
509  return do_minmax_body (args, nargout, true);
510 }
511 
512 /*
513 ## Test generic double class
514 %!assert (min ([1, 4, 2, 3]), 1)
515 %!assert (min ([1; -10; 5; -2]), -10)
516 %!assert (min ([4, 2i 4.999; -2, 2, 3+4i]), [-2, 2, 4.999])
517 ## Special routines for char arrays
518 %!assert (min (["abc", "ABC"]), 65)
519 %!assert (min (["abc"; "CBA"]), [67 66 65])
520 ## Special routines for logical arrays
521 %!assert (min (logical ([])), logical ([]))
522 %!assert (min (logical ([0 0 1 0])), false)
523 %!assert (min (logical ([0 0 1 0; 0 1 1 0])), logical ([0 0 1 0]))
524 ## Single values
525 %!assert (min (single ([1, 4, 2, 3])), single (1))
526 %!assert (min (single ([1; -10; 5; -2])), single (-10))
527 %!assert (min (single ([4, 2i 4.999; -2, 2, 3+4i])), single ([-2, 2, 4.999]))
528 ## Integer values
529 %!assert (min (uint8 ([1, 4, 2, 3])), uint8 (1))
530 %!assert (min (uint8 ([1; -10; 5; -2])), uint8 (-10))
531 %!assert (min (int8 ([1, 4, 2, 3])), int8 (1))
532 %!assert (min (int8 ([1; -10; 5; -2])), int8 (-10))
533 %!assert (min (uint16 ([1, 4, 2, 3])), uint16 (1))
534 %!assert (min (uint16 ([1; -10; 5; -2])), uint16 (-10))
535 %!assert (min (int16 ([1, 4, 2, 3])), int16 (1))
536 %!assert (min (int16 ([1; -10; 5; -2])), int16 (-10))
537 %!assert (min (uint32 ([1, 4, 2, 3])), uint32 (1))
538 %!assert (min (uint32 ([1; -10; 5; -2])), uint32 (-10))
539 %!assert (min (int32 ([1, 4, 2, 3])), int32 (1))
540 %!assert (min (int32 ([1; -10; 5; -2])), int32 (-10))
541 %!assert (min (uint64 ([1, 4, 2, 3])), uint64 (1))
542 %!assert (min (uint64 ([1; -10; 5; -2])), uint64 (-10))
543 %!assert (min (int64 ([1, 4, 2, 3])), int64 (1))
544 %!assert (min (int64 ([1; -10; 5; -2])), int64 (-10))
545 ## Sparse double values
546 %!assert (min (sparse ([1, 4, 2, 3])), sparse (1))
547 %!assert (min (sparse ([1; -10; 5; -2])), sparse(-10))
548 ## FIXME: sparse doesn't order complex values by phase angle
549 %!test <51307>
550 %! assert (min (sparse ([4, 2i 4.999; -2, 2, 3+4i])), sparse ([-2, 2, 4.999]));
551 
552 ## Test dimension argument
553 %!test
554 %! x = reshape (1:8, [2,2,2]);
555 %! assert (min (x, [], 1), reshape ([1, 3, 5, 7], [1,2,2]));
556 %! assert (min (x, [], 2), reshape ([1, 2, 5, 6], [2,1,2]));
557 %! [y, i] = min (x, [], 3);
558 %! assert (ndims (y), 2);
559 %! assert (y, [1, 3; 2, 4]);
560 %! assert (ndims (i), 2);
561 %! assert (i, [1, 1; 1, 1]);
562 
563 ## Test 2-output forms for various arg types
564 ## Special routines for char arrays
565 %!test
566 %! [y, i] = min (["abc", "ABC"]);
567 %! assert (y, 65);
568 %! assert (i, 4);
569 ## Special routines for logical arrays
570 %!test
571 %! x = logical ([0 0 1 0]);
572 %! [y, i] = min (x);
573 %! assert (y, false);
574 %! assert (i, 1);
575 ## Special handling of ranges
576 %!test
577 %! rng = 1:2:10;
578 %! [y, i] = min (rng);
579 %! assert (y, 1);
580 %! assert (i, 1);
581 %! rng = 10:-2:1;
582 %! [y, i] = min (rng);
583 %! assert (y, 2);
584 %! assert (i, 5);
585 
586 ## Test 2-input calling form for various arg types
587 ## Test generic double class
588 %!test
589 %! x = [1, 2, 3, 4]; y = fliplr (x);
590 %! assert (min (x, y), [1 2 2 1]);
591 %! assert (min (x, 3), [1 2 3 3]);
592 %! assert (min (2, x), [1 2 2 2]);
593 %! assert (min (x, 2.1i), [1 2 2.1i 2.1i]);
594 ## FIXME: Ordering of complex results with equal magnitude is not by phase
595 ## angle in the 2-input form. Instead, it is in the order in which it
596 ## appears in the argument list.
597 %!test <51307>
598 %! x = [1, 2, 3, 4]; y = fliplr (x);
599 %! assert (min (x, 2i), [2i 2i 3 4]);
600 ## Special routines for char arrays
601 %!assert (min ("abc", "b"), [97 98 98])
602 %!assert (min ("b", "cba"), [98 98 97])
603 ## Special handling for logical arrays
604 %!assert (min ([true false], false), [false false])
605 %!assert (min (true, [true false]), [true false])
606 ## Single values
607 %!test
608 %! x = single ([1, 2, 3, 4]); y = fliplr (x);
609 %! assert (min (x, y), single ([1 2 2 1]));
610 %! assert (min (x, 3), single ([1 2 3 3]));
611 %! assert (min (2, x), single ([1 2 2 2]));
612 %! assert (min (x, 2.1i), single ([1 2 2.1i 2.1i]));
613 ## Integer values
614 %!test
615 %! x = uint8 ([1, 2, 3, 4]); y = fliplr (x);
616 %! assert (min (x, y), uint8 ([1 2 2 1]));
617 %! assert (min (x, 3), uint8 ([1 2 3 3]));
618 %! assert (min (2, x), uint8 ([1 2 2 2]));
619 %! x = int8 ([1, 2, 3, 4]); y = fliplr (x);
620 %! assert (min (x, y), int8 ([1 2 2 1]));
621 %! assert (min (x, 3), int8 ([1 2 3 3]));
622 %! assert (min (2, x), int8 ([1 2 2 2]));
623 %! x = uint16 ([1, 2, 3, 4]); y = fliplr (x);
624 %! assert (min (x, y), uint16 ([1 2 2 1]));
625 %! assert (min (x, 3), uint16 ([1 2 3 3]));
626 %! assert (min (2, x), uint16 ([1 2 2 2]));
627 %! x = int16 ([1, 2, 3, 4]); y = fliplr (x);
628 %! assert (min (x, y), int16 ([1 2 2 1]));
629 %! assert (min (x, 3), int16 ([1 2 3 3]));
630 %! assert (min (2, x), int16 ([1 2 2 2]));
631 %! x = uint32 ([1, 2, 3, 4]); y = fliplr (x);
632 %! assert (min (x, y), uint32 ([1 2 2 1]));
633 %! assert (min (x, 3), uint32 ([1 2 3 3]));
634 %! assert (min (2, x), uint32 ([1 2 2 2]));
635 %! x = int32 ([1, 2, 3, 4]); y = fliplr (x);
636 %! assert (min (x, y), int32 ([1 2 2 1]));
637 %! assert (min (x, 3), int32 ([1 2 3 3]));
638 %! assert (min (2, x), int32 ([1 2 2 2]));
639 %! x = uint64 ([1, 2, 3, 4]); y = fliplr (x);
640 %! assert (min (x, y), uint64 ([1 2 2 1]));
641 %! assert (min (x, 3), uint64 ([1 2 3 3]));
642 %! assert (min (2, x), uint64 ([1 2 2 2]));
643 %! x = int64 ([1, 2, 3, 4]); y = fliplr (x);
644 %! assert (min (x, y), int64 ([1 2 2 1]));
645 %! assert (min (x, 3), int64 ([1 2 3 3]));
646 %! assert (min (2, x), int64 ([1 2 2 2]));
647 ## Sparse double values
648 %!test
649 %! x = sparse ([1, 2, 3, 4]); y = fliplr (x);
650 %! assert (min (x, y), sparse ([1 2 2 1]));
651 %! assert (min (x, 3), sparse ([1 2 3 3]));
652 %! assert (min (2, x), sparse ([1 2 2 2]));
653 %! assert (min (x, 2.1i), sparse ([1 2 2.1i 2.1i]));
654 
655 %!error min ()
656 %!error min (1, 2, 3, 4)
657 %!error <DIM must be a valid dimension> min ([1 2; 3 4], [], -3)
658 %!warning <second argument is ignored> min ([1 2 3 4], 2, 2);
659 %!error <wrong type argument 'cell'> min ({1 2 3 4})
660 %!error <cannot compute min \‍(cell, scalar\‍)> min ({1, 2, 3}, 2)
661 */
662 
663 DEFUN (max, args, nargout,
664  doc: /* -*- texinfo -*-
665 @deftypefn {} {@var{m} =} max (@var{x})
666 @deftypefnx {} {@var{m} =} max (@var{x}, [], @var{dim})
667 @deftypefnx {} {[@var{m}, @var{im}] =} max (@var{x})
668 @deftypefnx {} {@var{m} =} max (@var{x}, @var{y})
669 Find maximum values in the array @var{x}.
670 
671 For a vector argument, return the maximum value. For a matrix argument,
672 return a row vector with the maximum value of each column. For a
673 multi-dimensional array, @code{max} operates along the first non-singleton
674 dimension.
675 
676 If the optional third argument @var{dim} is present then operate along
677 this dimension. In this case the second argument is ignored and should be
678 set to the empty matrix.
679 
680 For two inputs (@var{x} and @var{y}), return the pairwise maximum according to
681 the rules for @ref{Broadcasting}.
682 
683 Thus,
684 
685 @example
686 max (max (@var{x}))
687 @end example
688 
689 @noindent
690 returns the largest element of the 2-D matrix @var{x}, and
691 
692 @example
693 @group
694 max (2:5, pi)
695  @result{} 3.1416 3.1416 4.0000 5.0000
696 @end group
697 @end example
698 
699 @noindent
700 compares each element of the range @code{2:5} with @code{pi}, and returns a
701 row vector of the maximum values.
702 
703 For complex arguments, the magnitude of the elements are used for
704 comparison. If the magnitudes are identical, then the results are ordered
705 by phase angle in the range (-pi, pi]. Hence,
706 
707 @example
708 @group
709 max ([-1 i 1 -i])
710  @result{} -1
711 @end group
712 @end example
713 
714 @noindent
715 because all entries have magnitude 1, but -1 has the largest phase angle
716 with value pi.
717 
718 If called with one input and two output arguments, @code{max} also returns
719 the first index of the maximum value(s). Thus,
720 
721 @example
722 @group
723 [x, ix] = max ([1, 3, 5, 2, 5])
724  @result{} x = 5
725  ix = 3
726 @end group
727 @end example
728 @seealso{min, cummax, cummin}
729 @end deftypefn */)
730 {
731  return do_minmax_body (args, nargout, false);
732 }
733 
734 /*
735 ## Test generic double class
736 %!assert (max ([1, 4, 2, 3]), 4)
737 %!assert (max ([1; -10; 5; -2]), 5)
738 %!assert (max ([4, 2i 4.999; -2, 2, 3+4i]), [4, 2i, 3+4i])
739 ## Special routines for char arrays
740 %!assert (max (["abc", "ABC"]), 99)
741 %!assert (max (["abc"; "CBA"]), [97 98 99])
742 ## Special routines for logical arrays
743 %!assert (max (logical ([])), logical ([]))
744 %!assert (max (logical ([0 0 1 0])), true)
745 %!assert (max (logical ([0 0 1 0; 0 1 0 0])), logical ([0 1 1 0]))
746 ## Single values
747 %!assert (max (single ([1, 4, 2, 3])), single (4))
748 %!assert (max (single ([1; -10; 5; -2])), single (5))
749 %!assert (max (single ([4, 2i 4.999; -2, 2, 3+4i])), single ([4, 2i, 3+4i]))
750 ## Integer values
751 %!assert (max (uint8 ([1, 4, 2, 3])), uint8 (4))
752 %!assert (max (uint8 ([1; -10; 5; -2])), uint8 (5))
753 %!assert (max (int8 ([1, 4, 2, 3])), int8 (4))
754 %!assert (max (int8 ([1; -10; 5; -2])), int8 (5))
755 %!assert (max (uint16 ([1, 4, 2, 3])), uint16 (4))
756 %!assert (max (uint16 ([1; -10; 5; -2])), uint16 (5))
757 %!assert (max (int16 ([1, 4, 2, 3])), int16 (4))
758 %!assert (max (int16 ([1; -10; 5; -2])), int16 (5))
759 %!assert (max (uint32 ([1, 4, 2, 3])), uint32 (4))
760 %!assert (max (uint32 ([1; -10; 5; -2])), uint32 (5))
761 %!assert (max (int32 ([1, 4, 2, 3])), int32 (4))
762 %!assert (max (int32 ([1; -10; 5; -2])), int32 (5))
763 %!assert (max (uint64 ([1, 4, 2, 3])), uint64 (4))
764 %!assert (max (uint64 ([1; -10; 5; -2])), uint64 (5))
765 %!assert (max (int64 ([1, 4, 2, 3])), int64 (4))
766 %!assert (max (int64 ([1; -10; 5; -2])), int64 (5))
767 ## Sparse double values
768 %!assert (max (sparse ([1, 4, 2, 3])), sparse (4))
769 %!assert (max (sparse ([1; -10; 5; -2])), sparse(5))
770 %!assert (max (sparse ([4, 2i 4.999; -2, 2, 3+4i])), sparse ([4, 2i, 3+4i]))
771 
772 ## Test dimension argument
773 %!test
774 %! x = reshape (1:8, [2,2,2]);
775 %! assert (min (x, [], 1), reshape ([1, 3, 5, 7], [1,2,2]));
776 %! assert (min (x, [], 2), reshape ([1, 2, 5, 6], [2,1,2]));
777 %! [y, i] = min (x, [], 3);
778 %! assert (ndims (y), 2);
779 %! assert (y, [1, 3; 2, 4]);
780 %! assert (ndims (i), 2);
781 %! assert (i, [1, 1; 1, 1]);
782 
783 ## Test 2-output forms for various arg types
784 ## Special routines for char arrays
785 %!test
786 %! [y, i] = max (["abc", "ABC"]);
787 %! assert (y, 99);
788 %! assert (i, 3);
789 ## Special routines for logical arrays
790 %!test
791 %! x = logical ([0 0 1 0]);
792 %! [y, i] = max (x);
793 %! assert (y, true);
794 %! assert (i, 3);
795 ## Special handling of ranges
796 %!test
797 %! rng = 1:2:10;
798 %! [y, i] = max (rng);
799 %! assert (y, 9);
800 %! assert (i, 5);
801 %! rng = 10:-2:1;
802 %! [y, i] = max (rng);
803 %! assert (y, 10);
804 %! assert (i, 1);
805 
806 ## Test 2-input calling form for various arg types
807 ## Test generic double class
808 %!test
809 %! x = [1, 2, 3, 4]; y = fliplr (x);
810 %! assert (max (x, y), [4 3 3 4]);
811 %! assert (max (x, 3), [3 3 3 4]);
812 %! assert (max (2, x), [2 2 3 4]);
813 %! assert (max (x, 2.1i), [2.1i 2.1i 3 4]);
814 ## FIXME: Ordering of complex results with equal magnitude is not by phase
815 ## angle in the 2-input form. Instead, it is in the order in which it
816 ## appears in the argument list.
817 %!test <51307>
818 %! x = [1, 2, 3, 4]; y = fliplr (x);
819 %! assert (max (x, 2i), [2i 2i 3 4]);
820 ## Special routines for char arrays
821 %!assert (max ("abc", "b"), [98 98 99])
822 %!assert (max ("b", "cba"), [99 98 98])
823 ## Special handling for logical arrays
824 %!assert (max ([true false], false), [true false])
825 %!assert (max (true, [false false]), [true true])
826 ## Single values
827 %!test
828 %! x = single ([1, 2, 3, 4]); y = fliplr (x);
829 %! assert (max (x, y), single ([4 3 3 4]));
830 %! assert (max (x, 3), single ([3 3 3 4]));
831 %! assert (max (2, x), single ([2 2 3 4]));
832 %! assert (max (x, 2.1i), single ([2.1i 2.1i 3 4]));
833 ## Integer values
834 %!test
835 %! x = uint8 ([1, 2, 3, 4]); y = fliplr (x);
836 %! assert (max (x, y), uint8 ([4 3 3 4]));
837 %! assert (max (x, 3), uint8 ([3 3 3 4]));
838 %! assert (max (2, x), uint8 ([2 2 3 4]));
839 %! x = int8 ([1, 2, 3, 4]); y = fliplr (x);
840 %! assert (max (x, y), int8 ([4 3 3 4]));
841 %! assert (max (x, 3), int8 ([3 3 3 4]));
842 %! assert (max (2, x), int8 ([2 2 3 4]));
843 %! x = uint16 ([1, 2, 3, 4]); y = fliplr (x);
844 %! assert (max (x, y), uint16 ([4 3 3 4]));
845 %! assert (max (x, 3), uint16 ([3 3 3 4]));
846 %! assert (max (2, x), uint16 ([2 2 3 4]));
847 %! x = int16 ([1, 2, 3, 4]); y = fliplr (x);
848 %! assert (max (x, y), int16 ([4 3 3 4]));
849 %! assert (max (x, 3), int16 ([3 3 3 4]));
850 %! assert (max (2, x), int16 ([2 2 3 4]));
851 %! x = uint32 ([1, 2, 3, 4]); y = fliplr (x);
852 %! assert (max (x, y), uint32 ([4 3 3 4]));
853 %! assert (max (x, 3), uint32 ([3 3 3 4]));
854 %! assert (max (2, x), uint32 ([2 2 3 4]));
855 %! x = int32 ([1, 2, 3, 4]); y = fliplr (x);
856 %! assert (max (x, y), int32 ([4 3 3 4]));
857 %! assert (max (x, 3), int32 ([3 3 3 4]));
858 %! assert (max (2, x), int32 ([2 2 3 4]));
859 %! x = uint64 ([1, 2, 3, 4]); y = fliplr (x);
860 %! assert (max (x, y), uint64 ([4 3 3 4]));
861 %! assert (max (x, 3), uint64 ([3 3 3 4]));
862 %! assert (max (2, x), uint64 ([2 2 3 4]));
863 %! x = int64 ([1, 2, 3, 4]); y = fliplr (x);
864 %! assert (max (x, y), int64 ([4 3 3 4]));
865 %! assert (max (x, 3), int64 ([3 3 3 4]));
866 %! assert (max (2, x), int64 ([2 2 3 4]));
867 ## Sparse double values
868 %!test
869 %! x = sparse ([1, 2, 3, 4]); y = fliplr (x);
870 %! assert (max (x, y), sparse ([4 3 3 4]));
871 %! assert (max (x, 3), sparse ([3 3 3 4]));
872 %! assert (max (2, x), sparse ([2 2 3 4]));
873 %! assert (max (x, 2.1i), sparse ([2.1i 2.1i 3 4]));
874 
875 ## Test for bug #40743
876 %!assert <*40743> (max (zeros (1,0), ones (1,1)), zeros (1,0))
877 %!assert <*40743> (max (sparse (zeros (1,0)), sparse (ones (1,1))),
878 %! sparse (zeros (1,0)))
879 
880 %!error max ()
881 %!error max (1, 2, 3, 4)
882 %!error <DIM must be a valid dimension> max ([1 2; 3 4], [], -3)
883 %!warning <second argument is ignored> max ([1 2 3 4], 2, 2);
884 %!error <wrong type argument 'cell'> max ({1 2 3 4})
885 %!error <cannot compute max \‍(cell, scalar\‍)> max ({1, 2, 3}, 2)
886 
887 */
888 
889 template <typename ArrayType>
890 static octave_value_list
891 do_cumminmax_red_op (const octave_value& arg,
892  int nargout, int dim, bool ismin)
893 {
894  octave_value_list retval (nargout > 1 ? 2 : 1);
895  ArrayType array = octave_value_extract<ArrayType> (arg);
896 
897  if (nargout <= 1)
898  {
899  if (ismin)
900  retval(0) = array.cummin (dim);
901  else
902  retval(0) = array.cummax (dim);
903  }
904  else
905  {
906  retval.resize (2);
908  if (ismin)
909  retval(0) = array.cummin (idx, dim);
910  else
911  retval(0) = array.cummax (idx, dim);
912 
913  retval(1) = octave_value (idx, true, true);
914  }
915 
916  return retval;
917 }
918 
919 static octave_value_list
920 do_cumminmax_body (const octave_value_list& args,
921  int nargout, bool ismin)
922 {
923  int nargin = args.length ();
924 
925  if (nargin < 1 || nargin > 2)
926  print_usage ();
927 
928  const char *fcn = (ismin ? "cummin" : "cummax");
929 
930  octave_value arg = args(0);
931  int dim = -1;
932  if (nargin == 2)
933  {
934  dim = args(1).int_value (true) - 1;
935 
936  if (dim < 0)
937  error ("%s: DIM must be a valid dimension", fcn);
938  }
939 
940  octave_value_list retval;
941 
942  switch (arg.builtin_type ())
943  {
944  case btyp_double:
945  retval = do_cumminmax_red_op<NDArray> (arg, nargout, dim, ismin);
946  break;
947 
948  case btyp_complex:
949  retval = do_cumminmax_red_op<ComplexNDArray> (arg, nargout, dim,
950  ismin);
951  break;
952 
953  case btyp_float:
954  retval = do_cumminmax_red_op<FloatNDArray> (arg, nargout, dim, ismin);
955  break;
956 
957  case btyp_float_complex:
958  retval = do_cumminmax_red_op<FloatComplexNDArray> (arg, nargout, dim,
959  ismin);
960  break;
961 
962 #define MAKE_INT_BRANCH(X) \
963  case btyp_ ## X: \
964  retval = do_cumminmax_red_op<X ## NDArray> (arg, nargout, dim, ismin); \
965  break;
966 
967  MAKE_INT_BRANCH (int8);
968  MAKE_INT_BRANCH (int16);
969  MAKE_INT_BRANCH (int32);
970  MAKE_INT_BRANCH (int64);
971  MAKE_INT_BRANCH (uint8);
972  MAKE_INT_BRANCH (uint16);
973  MAKE_INT_BRANCH (uint32);
974  MAKE_INT_BRANCH (uint64);
975 
976 #undef MAKE_INT_BRANCH
977 
978  case btyp_bool:
979  {
980  retval = do_cumminmax_red_op<int8NDArray> (arg, nargout, dim,
981  ismin);
982  if (retval.length () > 0)
983  retval(0) = retval(0).bool_array_value ();
984  }
985  break;
986 
987  default:
988  err_wrong_type_arg (fcn, arg);
989  }
990 
991  return retval;
992 }
993 
994 DEFUN (cummin, args, nargout,
995  doc: /* -*- texinfo -*-
996 @deftypefn {} {@var{M} =} cummin (@var{x})
997 @deftypefnx {} {@var{M} =} cummin (@var{x}, @var{dim})
998 @deftypefnx {} {[@var{M}, @var{IM}] =} cummin (@var{x})
999 Return the cumulative minimum values along dimension @var{dim}.
1000 
1001 If @var{dim} is unspecified it defaults to column-wise operation. For
1002 example:
1003 
1004 @example
1005 @group
1006 cummin ([5 4 6 2 3 1])
1007  @result{} 5 4 4 2 2 1
1008 @end group
1009 @end example
1010 
1011 If called with two output arguments the index of the minimum value is also
1012 returned.
1013 
1014 @example
1015 @group
1016 [M, IM] = cummin ([5 4 6 2 3 1])
1017 @result{}
1018 M = 5 4 4 2 2 1
1019 IM = 1 2 2 4 4 6
1020 @end group
1021 @end example
1022 
1023 @seealso{cummax, min, max}
1024 @end deftypefn */)
1025 {
1026  return do_cumminmax_body (args, nargout, true);
1027 }
1028 
1029 /*
1030 %!assert (cummin ([1, 4, 2, 3]), [1 1 1 1])
1031 %!assert (cummin ([1; -10; 5; -2]), [1; -10; -10; -10])
1032 %!assert (cummin ([4, i; -2, 2]), [4, i; -2, i])
1033 %!assert (cummin ([1 2; NaN 1], 2), [1 1; NaN 1])
1034 
1035 %!test
1036 %! x = reshape (1:8, [2,2,2]);
1037 %! assert (cummin (x, 1), reshape ([1 1 3 3 5 5 7 7], [2,2,2]));
1038 %! assert (cummin (x, 2), reshape ([1 2 1 2 5 6 5 6], [2,2,2]));
1039 %! [w, iw] = cummin (x, 3);
1040 %! assert (ndims (w), 3);
1041 %! assert (w, repmat ([1 3; 2 4], [1 1 2]));
1042 %! assert (ndims (iw), 3);
1043 %! assert (iw, ones (2,2,2));
1044 
1045 %!error cummin ()
1046 %!error cummin (1, 2, 3)
1047 */
1048 
1049 DEFUN (cummax, args, nargout,
1050  doc: /* -*- texinfo -*-
1051 @deftypefn {} {@var{M} =} cummax (@var{x})
1052 @deftypefnx {} {@var{M} =} cummax (@var{x}, @var{dim})
1053 @deftypefnx {} {[@var{M}, @var{IM}] =} cummax (@dots{})
1054 Return the cumulative maximum values along dimension @var{dim}.
1055 
1056 If @var{dim} is unspecified it defaults to column-wise operation. For
1057 example:
1058 
1059 @example
1060 @group
1061 cummax ([1 3 2 6 4 5])
1062  @result{} 1 3 3 6 6 6
1063 @end group
1064 @end example
1065 
1066 If called with two output arguments the index of the maximum value is also
1067 returned.
1068 
1069 @example
1070 @group
1071 [w, iw] = cummax ([1 3 2 6 4 5])
1072 @result{}
1073 M = 1 3 3 6 6 6
1074 IM = 1 2 2 4 4 4
1075 @end group
1076 @end example
1077 
1078 @seealso{cummin, max, min}
1079 @end deftypefn */)
1080 {
1081  return do_cumminmax_body (args, nargout, false);
1082 }
1083 
1084 /*
1085 %!assert (cummax ([1, 4, 2, 3]), [1 4 4 4])
1086 %!assert (cummax ([1; -10; 5; -2]), [1; 1; 5; 5])
1087 %!assert (cummax ([4, i 4.9, -2, 2, 3+4i]), [4, 4, 4.9, 4.9, 4.9, 3+4i])
1088 %!assert (cummax ([1 NaN 0; NaN NaN 1], 2), [1 1 1; NaN NaN 1])
1089 
1090 %!test
1091 %! x = reshape (8:-1:1, [2,2,2]);
1092 %! assert (cummax (x, 1), reshape ([8 8 6 6 4 4 2 2], [2,2,2]));
1093 %! assert (cummax (x, 2), reshape ([8 7 8 7 4 3 4 3], [2,2,2]));
1094 %! [w, iw] = cummax (x, 3);
1095 %! assert (ndims (w), 3);
1096 %! assert (w, repmat ([8 6; 7 5], [1 1 2]));
1097 %! assert (ndims (iw), 3);
1098 %! assert (iw, ones (2,2,2));
1099 
1100 %!error cummax ()
1101 %!error cummax (1, 2, 3)
1102 */
1103 
1104 OCTAVE_END_NAMESPACE(octave)
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:207
bool isempty() const
Size of the specified dimension.
Definition: Array.h:651
octave_idx_type numel() const
Number of elements in the array.
Definition: Array.h:414
boolNDArray any(int dim=-1) const
Definition: boolNDArray.cc:67
boolNDArray all(int dim=-1) const
Definition: boolNDArray.cc:61
charNDArray max(int dim=-1) const
Definition: chNDArray.cc:142
charNDArray min(int dim=-1) const
Definition: chNDArray.cc:154
octave_idx_type length() const
Definition: ovl.h:113
boolNDArray bool_array_value(bool warn=false) const
Definition: ov.h:891
bool is_scalar_type() const
Definition: ov.h:744
octave::range< double > range_value() const
Definition: ov.h:985
bool is_range() const
Definition: ov.h:646
bool issparse() const
Definition: ov.h:753
std::string type_name() const
Definition: ov.h:1345
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov.h:580
builtin_type_t builtin_type() const
Definition: ov.h:690
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage(void)
Definition: defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
void warning(const char *fmt,...)
Definition: error.cc:1063
void() error(const char *fmt,...)
Definition: error.cc:988
void err_wrong_type_arg(const char *name, const char *s)
Definition: errwarn.cc:166
F77_RET_T const F77_DBLE * x
octave_value do_minmax_bin_op< charNDArray >(const octave_value &argx, const octave_value &argy, bool ismin)
Definition: max.cc:210
#define MAKE_INT_BRANCH(X)
octave_value_list do_minmax_red_op< boolNDArray >(const octave_value &arg, int nargout, int dim, bool ismin)
Definition: max.cc:118
octave_value_list do_minmax_red_op< charNDArray >(const octave_value &arg, int nargout, int dim, bool ismin)
Definition: max.cc:88
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
builtin_type_t btyp_mixed_numeric(builtin_type_t x, builtin_type_t y)
Determine the resulting type for a possible mixed-type operation.
Definition: ov-base.cc:67
builtin_type_t
Definition: ov-base.h:83
@ btyp_float_complex
Definition: ov-base.h:87
@ btyp_double
Definition: ov-base.h:84
@ btyp_float
Definition: ov-base.h:85
@ btyp_bool
Definition: ov-base.h:96
@ btyp_char
Definition: ov-base.h:97
@ btyp_complex
Definition: ov-base.h:86
charNDArray octave_value_extract< charNDArray >(const octave_value &v)
Definition: ov.h:1736