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