GNU Octave 7.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-2022 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
47OCTAVE_NAMESPACE_BEGIN
48
49template <typename ArrayType>
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
86template <>
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).
116template <>
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
157template <typename ArrayType>
158static octave_value
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
208template <>
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
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 *func = (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", func);
263
264 if (! args(1).isempty ())
265 warning ("%s: second argument is ignored", func);
266 }
267
268 switch (arg.builtin_type ())
269 {
270 case btyp_double:
271 {
272 if (arg.is_range () && (dim == -1 || dim == 1))
273 {
274 range<double> range = arg.range_value ();
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 () : 1);
294 }
295 }
296 else if (arg.issparse ())
297 retval = do_minmax_red_op<SparseMatrix> (arg, nargout, dim,
298 ismin);
299 else
300 retval = do_minmax_red_op<NDArray> (arg, nargout, dim, ismin);
301
302 }
303 break;
304
305 case btyp_complex:
306 {
307 if (arg.issparse ())
308 retval = do_minmax_red_op<SparseComplexMatrix> (arg, nargout, dim,
309 ismin);
310 else
311 retval = do_minmax_red_op<ComplexNDArray> (arg, nargout, dim,
312 ismin);
313 }
314 break;
315
316 case btyp_float:
317 retval = do_minmax_red_op<FloatNDArray> (arg, nargout, dim, ismin);
318 break;
319
321 retval = do_minmax_red_op<FloatComplexNDArray> (arg, nargout, dim,
322 ismin);
323 break;
324
325 case btyp_char:
326 retval = do_minmax_red_op<charNDArray> (arg, nargout, dim, ismin);
327 break;
328
329#define MAKE_INT_BRANCH(X) \
330 case btyp_ ## X: \
331 retval = do_minmax_red_op<X ## NDArray> (arg, nargout, dim, ismin); \
332 break;
333
334 MAKE_INT_BRANCH (int8);
335 MAKE_INT_BRANCH (int16);
336 MAKE_INT_BRANCH (int32);
337 MAKE_INT_BRANCH (int64);
338 MAKE_INT_BRANCH (uint8);
339 MAKE_INT_BRANCH (uint16);
340 MAKE_INT_BRANCH (uint32);
341 MAKE_INT_BRANCH (uint64);
342
343#undef MAKE_INT_BRANCH
344
345 case btyp_bool:
346 retval = do_minmax_red_op<boolNDArray> (arg, nargout, dim, ismin);
347 break;
348
349 default:
350 err_wrong_type_arg (func, arg);
351 }
352 }
353 else
354 {
355 octave_value argx = args(0);
356 octave_value argy = args(1);
357 builtin_type_t xtyp = argx.builtin_type ();
358 builtin_type_t ytyp = argy.builtin_type ();
359 builtin_type_t rtyp;
360 if (xtyp == btyp_char && ytyp == btyp_char)
361 rtyp = btyp_char;
362 // FIXME: This is what should happen when boolNDArray has max()
363 // else if (xtyp == btyp_bool && ytyp == btyp_bool)
364 // rtyp = btyp_bool;
365 else
366 rtyp = btyp_mixed_numeric (xtyp, ytyp);
367
368 switch (rtyp)
369 {
370 case btyp_double:
371 {
372 if ((argx.issparse ()
373 && (argy.issparse () || argy.is_scalar_type ()))
374 || (argy.issparse () && argx.is_scalar_type ()))
375 retval = do_minmax_bin_op<SparseMatrix> (argx, argy, ismin);
376 else
377 retval = do_minmax_bin_op<NDArray> (argx, argy, ismin);
378 }
379 break;
380
381 case btyp_complex:
382 {
383 if ((argx.issparse ()
384 && (argy.issparse () || argy.is_scalar_type ()))
385 || (argy.issparse () && argx.is_scalar_type ()))
386 retval = do_minmax_bin_op<SparseComplexMatrix> (argx, argy,
387 ismin);
388 else
389 retval = do_minmax_bin_op<ComplexNDArray> (argx, argy, ismin);
390 }
391 break;
392
393 case btyp_float:
394 retval = do_minmax_bin_op<FloatNDArray> (argx, argy, ismin);
395 break;
396
398 retval = do_minmax_bin_op<FloatComplexNDArray> (argx, argy, ismin);
399 break;
400
401 case btyp_char:
402 retval = do_minmax_bin_op<charNDArray> (argx, argy, ismin);
403 break;
404
405#define MAKE_INT_BRANCH(X) \
406 case btyp_ ## X: \
407 retval = do_minmax_bin_op<X ## NDArray> (argx, argy, ismin); \
408 break;
409
410 MAKE_INT_BRANCH (int8);
411 MAKE_INT_BRANCH (int16);
412 MAKE_INT_BRANCH (int32);
413 MAKE_INT_BRANCH (int64);
414 MAKE_INT_BRANCH (uint8);
415 MAKE_INT_BRANCH (uint16);
416 MAKE_INT_BRANCH (uint32);
417 MAKE_INT_BRANCH (uint64);
418
419#undef MAKE_INT_BRANCH
420
421 // FIXME: This is what should happen when boolNDArray has max()
422 // case btyp_bool:
423 // retval = do_minmax_bin_op<boolNDArray> (argx, argy, ismin);
424 // break;
425
426 default:
427 error ("%s: cannot compute %s (%s, %s)", func, func,
428 argx.type_name ().c_str (), argy.type_name ().c_str ());
429 }
430
431 // FIXME: Delete when boolNDArray has max()
432 if (xtyp == btyp_bool && ytyp == btyp_bool)
433 retval(0) = retval(0).bool_array_value ();
434
435 }
436
437 return retval;
438}
439
440DEFUN (min, args, nargout,
441 doc: /* -*- texinfo -*-
442@deftypefn {} {} min (@var{x})
443@deftypefnx {} {} min (@var{x}, [], @var{dim})
444@deftypefnx {} {[@var{w}, @var{iw}] =} min (@var{x})
445@deftypefnx {} {} min (@var{x}, @var{y})
446Find minimum values in the array @var{x}.
447
448For a vector argument, return the minimum value. For a matrix argument,
449return a row vector with the minimum value of each column. For a
450multi-dimensional array, @code{min} operates along the first non-singleton
451dimension.
452
453If the optional third argument @var{dim} is present then operate along
454this dimension. In this case the second argument is ignored and should be
455set to the empty matrix.
456
457For two inputs (@var{x} and @var{y}), return the pairwise minimum according to
458the rules for @ref{Broadcasting}.
459
460Thus,
461
462@example
463min (min (@var{x}))
464@end example
465
466@noindent
467returns the smallest element of the 2-D matrix @var{x}, and
468
469@example
470@group
471min (2:5, pi)
472 @result{} 2.0000 3.0000 3.1416 3.1416
473@end group
474@end example
475
476@noindent
477compares each element of the range @code{2:5} with @code{pi}, and returns a
478row vector of the minimum values.
479
480For complex arguments, the magnitude of the elements are used for
481comparison. If the magnitudes are identical, then the results are ordered
482by phase angle in the range (-pi, pi]. Hence,
483
484@example
485@group
486min ([-1 i 1 -i])
487 @result{} -i
488@end group
489@end example
490
491@noindent
492because all entries have magnitude 1, but -i has the smallest phase angle
493with value -pi/2.
494
495If called with one input and two output arguments, @code{min} also returns
496the first index of the minimum value(s). Thus,
497
498@example
499@group
500[x, ix] = min ([1, 3, 0, 2, 0])
501 @result{} x = 0
502 ix = 3
503@end group
504@end example
505@seealso{max, cummin, cummax}
506@end deftypefn */)
507{
508 return do_minmax_body (args, nargout, true);
509}
510
511/*
512## Test generic double class
513%!assert (min ([1, 4, 2, 3]), 1)
514%!assert (min ([1; -10; 5; -2]), -10)
515%!assert (min ([4, 2i 4.999; -2, 2, 3+4i]), [-2, 2, 4.999])
516## Special routines for char arrays
517%!assert (min (["abc", "ABC"]), 65)
518%!assert (min (["abc"; "CBA"]), [67 66 65])
519## Special routines for logical arrays
520%!assert (min (logical ([])), logical ([]))
521%!assert (min (logical ([0 0 1 0])), false)
522%!assert (min (logical ([0 0 1 0; 0 1 1 0])), logical ([0 0 1 0]))
523## Single values
524%!assert (min (single ([1, 4, 2, 3])), single (1))
525%!assert (min (single ([1; -10; 5; -2])), single (-10))
526%!assert (min (single ([4, 2i 4.999; -2, 2, 3+4i])), single ([-2, 2, 4.999]))
527## Integer values
528%!assert (min (uint8 ([1, 4, 2, 3])), uint8 (1))
529%!assert (min (uint8 ([1; -10; 5; -2])), uint8 (-10))
530%!assert (min (int8 ([1, 4, 2, 3])), int8 (1))
531%!assert (min (int8 ([1; -10; 5; -2])), int8 (-10))
532%!assert (min (uint16 ([1, 4, 2, 3])), uint16 (1))
533%!assert (min (uint16 ([1; -10; 5; -2])), uint16 (-10))
534%!assert (min (int16 ([1, 4, 2, 3])), int16 (1))
535%!assert (min (int16 ([1; -10; 5; -2])), int16 (-10))
536%!assert (min (uint32 ([1, 4, 2, 3])), uint32 (1))
537%!assert (min (uint32 ([1; -10; 5; -2])), uint32 (-10))
538%!assert (min (int32 ([1, 4, 2, 3])), int32 (1))
539%!assert (min (int32 ([1; -10; 5; -2])), int32 (-10))
540%!assert (min (uint64 ([1, 4, 2, 3])), uint64 (1))
541%!assert (min (uint64 ([1; -10; 5; -2])), uint64 (-10))
542%!assert (min (int64 ([1, 4, 2, 3])), int64 (1))
543%!assert (min (int64 ([1; -10; 5; -2])), int64 (-10))
544## Sparse double values
545%!assert (min (sparse ([1, 4, 2, 3])), sparse (1))
546%!assert (min (sparse ([1; -10; 5; -2])), sparse(-10))
547## FIXME: sparse doesn't order complex values by phase angle
548%!test <51307>
549%! assert (min (sparse ([4, 2i 4.999; -2, 2, 3+4i])), sparse ([-2, 2, 4.999]));
550
551## Test dimension argument
552%!test
553%! x = reshape (1:8, [2,2,2]);
554%! assert (min (x, [], 1), reshape ([1, 3, 5, 7], [1,2,2]));
555%! assert (min (x, [], 2), reshape ([1, 2, 5, 6], [2,1,2]));
556%! [y, i] = min (x, [], 3);
557%! assert (ndims (y), 2);
558%! assert (y, [1, 3; 2, 4]);
559%! assert (ndims (i), 2);
560%! assert (i, [1, 1; 1, 1]);
561
562## Test 2-output forms for various arg types
563## Special routines for char arrays
564%!test
565%! [y, i] = min (["abc", "ABC"]);
566%! assert (y, 65);
567%! assert (i, 4);
568## Special routines for logical arrays
569%!test
570%! x = logical ([0 0 1 0]);
571%! [y, i] = min (x);
572%! assert (y, false);
573%! assert (i, 1);
574## Special handling of ranges
575%!test
576%! rng = 1:2:10;
577%! [y, i] = min (rng);
578%! assert (y, 1);
579%! assert (i, 1);
580%! rng = 10:-2:1;
581%! [y, i] = min (rng);
582%! assert (y, 2);
583%! assert (i, 5);
584
585## Test 2-input calling form for various arg types
586## Test generic double class
587%!test
588%! x = [1, 2, 3, 4]; y = fliplr (x);
589%! assert (min (x, y), [1 2 2 1]);
590%! assert (min (x, 3), [1 2 3 3]);
591%! assert (min (2, x), [1 2 2 2]);
592%! assert (min (x, 2.1i), [1 2 2.1i 2.1i]);
593## FIXME: Ordering of complex results with equal magnitude is not by phase
594## angle in the 2-input form. Instead, it is in the order in which it
595## appears in the argument list.
596%!test <51307>
597%! x = [1, 2, 3, 4]; y = fliplr (x);
598%! assert (min (x, 2i), [2i 2i 3 4]);
599## Special routines for char arrays
600%!assert (min ("abc", "b"), [97 98 98])
601%!assert (min ("b", "cba"), [98 98 97])
602## Special handling for logical arrays
603%!assert (min ([true false], false), [false false])
604%!assert (min (true, [true false]), [true false])
605## Single values
606%!test
607%! x = single ([1, 2, 3, 4]); y = fliplr (x);
608%! assert (min (x, y), single ([1 2 2 1]));
609%! assert (min (x, 3), single ([1 2 3 3]));
610%! assert (min (2, x), single ([1 2 2 2]));
611%! assert (min (x, 2.1i), single ([1 2 2.1i 2.1i]));
612## Integer values
613%!test
614%! x = uint8 ([1, 2, 3, 4]); y = fliplr (x);
615%! assert (min (x, y), uint8 ([1 2 2 1]));
616%! assert (min (x, 3), uint8 ([1 2 3 3]));
617%! assert (min (2, x), uint8 ([1 2 2 2]));
618%! x = int8 ([1, 2, 3, 4]); y = fliplr (x);
619%! assert (min (x, y), int8 ([1 2 2 1]));
620%! assert (min (x, 3), int8 ([1 2 3 3]));
621%! assert (min (2, x), int8 ([1 2 2 2]));
622%! x = uint16 ([1, 2, 3, 4]); y = fliplr (x);
623%! assert (min (x, y), uint16 ([1 2 2 1]));
624%! assert (min (x, 3), uint16 ([1 2 3 3]));
625%! assert (min (2, x), uint16 ([1 2 2 2]));
626%! x = int16 ([1, 2, 3, 4]); y = fliplr (x);
627%! assert (min (x, y), int16 ([1 2 2 1]));
628%! assert (min (x, 3), int16 ([1 2 3 3]));
629%! assert (min (2, x), int16 ([1 2 2 2]));
630%! x = uint32 ([1, 2, 3, 4]); y = fliplr (x);
631%! assert (min (x, y), uint32 ([1 2 2 1]));
632%! assert (min (x, 3), uint32 ([1 2 3 3]));
633%! assert (min (2, x), uint32 ([1 2 2 2]));
634%! x = int32 ([1, 2, 3, 4]); y = fliplr (x);
635%! assert (min (x, y), int32 ([1 2 2 1]));
636%! assert (min (x, 3), int32 ([1 2 3 3]));
637%! assert (min (2, x), int32 ([1 2 2 2]));
638%! x = uint64 ([1, 2, 3, 4]); y = fliplr (x);
639%! assert (min (x, y), uint64 ([1 2 2 1]));
640%! assert (min (x, 3), uint64 ([1 2 3 3]));
641%! assert (min (2, x), uint64 ([1 2 2 2]));
642%! x = int64 ([1, 2, 3, 4]); y = fliplr (x);
643%! assert (min (x, y), int64 ([1 2 2 1]));
644%! assert (min (x, 3), int64 ([1 2 3 3]));
645%! assert (min (2, x), int64 ([1 2 2 2]));
646## Sparse double values
647%!test
648%! x = sparse ([1, 2, 3, 4]); y = fliplr (x);
649%! assert (min (x, y), sparse ([1 2 2 1]));
650%! assert (min (x, 3), sparse ([1 2 3 3]));
651%! assert (min (2, x), sparse ([1 2 2 2]));
652%! assert (min (x, 2.1i), sparse ([1 2 2.1i 2.1i]));
653
654%!error min ()
655%!error min (1, 2, 3, 4)
656%!error <DIM must be a valid dimension> min ([1 2; 3 4], [], -3)
657%!warning <second argument is ignored> min ([1 2 3 4], 2, 2);
658%!error <wrong type argument 'cell'> min ({1 2 3 4})
659%!error <cannot compute min \‍(cell, scalar\‍)> min ({1, 2, 3}, 2)
660*/
661
662DEFUN (max, args, nargout,
663 doc: /* -*- texinfo -*-
664@deftypefn {} {} max (@var{x})
665@deftypefnx {} {} max (@var{x}, [], @var{dim})
666@deftypefnx {} {[@var{w}, @var{iw}] =} max (@var{x})
667@deftypefnx {} {} max (@var{x}, @var{y})
668Find maximum values in the array @var{x}.
669
670For a vector argument, return the maximum value. For a matrix argument,
671return a row vector with the maximum value of each column. For a
672multi-dimensional array, @code{max} operates along the first non-singleton
673dimension.
674
675If the optional third argument @var{dim} is present then operate along
676this dimension. In this case the second argument is ignored and should be
677set to the empty matrix.
678
679For two inputs (@var{x} and @var{y}), return the pairwise maximum according to
680the rules for @ref{Broadcasting}.
681
682Thus,
683
684@example
685max (max (@var{x}))
686@end example
687
688@noindent
689returns the largest element of the 2-D matrix @var{x}, and
690
691@example
692@group
693max (2:5, pi)
694 @result{} 3.1416 3.1416 4.0000 5.0000
695@end group
696@end example
697
698@noindent
699compares each element of the range @code{2:5} with @code{pi}, and returns a
700row vector of the maximum values.
701
702For complex arguments, the magnitude of the elements are used for
703comparison. If the magnitudes are identical, then the results are ordered
704by phase angle in the range (-pi, pi]. Hence,
705
706@example
707@group
708max ([-1 i 1 -i])
709 @result{} -1
710@end group
711@end example
712
713@noindent
714because all entries have magnitude 1, but -1 has the largest phase angle
715with value pi.
716
717If called with one input and two output arguments, @code{max} also returns
718the first index of the maximum value(s). Thus,
719
720@example
721@group
722[x, ix] = max ([1, 3, 5, 2, 5])
723 @result{} x = 5
724 ix = 3
725@end group
726@end example
727@seealso{min, cummax, cummin}
728@end deftypefn */)
729{
730 return do_minmax_body (args, nargout, false);
731}
732
733/*
734## Test generic double class
735%!assert (max ([1, 4, 2, 3]), 4)
736%!assert (max ([1; -10; 5; -2]), 5)
737%!assert (max ([4, 2i 4.999; -2, 2, 3+4i]), [4, 2i, 3+4i])
738## Special routines for char arrays
739%!assert (max (["abc", "ABC"]), 99)
740%!assert (max (["abc"; "CBA"]), [97 98 99])
741## Special routines for logical arrays
742%!assert (max (logical ([])), logical ([]))
743%!assert (max (logical ([0 0 1 0])), true)
744%!assert (max (logical ([0 0 1 0; 0 1 0 0])), logical ([0 1 1 0]))
745## Single values
746%!assert (max (single ([1, 4, 2, 3])), single (4))
747%!assert (max (single ([1; -10; 5; -2])), single (5))
748%!assert (max (single ([4, 2i 4.999; -2, 2, 3+4i])), single ([4, 2i, 3+4i]))
749## Integer values
750%!assert (max (uint8 ([1, 4, 2, 3])), uint8 (4))
751%!assert (max (uint8 ([1; -10; 5; -2])), uint8 (5))
752%!assert (max (int8 ([1, 4, 2, 3])), int8 (4))
753%!assert (max (int8 ([1; -10; 5; -2])), int8 (5))
754%!assert (max (uint16 ([1, 4, 2, 3])), uint16 (4))
755%!assert (max (uint16 ([1; -10; 5; -2])), uint16 (5))
756%!assert (max (int16 ([1, 4, 2, 3])), int16 (4))
757%!assert (max (int16 ([1; -10; 5; -2])), int16 (5))
758%!assert (max (uint32 ([1, 4, 2, 3])), uint32 (4))
759%!assert (max (uint32 ([1; -10; 5; -2])), uint32 (5))
760%!assert (max (int32 ([1, 4, 2, 3])), int32 (4))
761%!assert (max (int32 ([1; -10; 5; -2])), int32 (5))
762%!assert (max (uint64 ([1, 4, 2, 3])), uint64 (4))
763%!assert (max (uint64 ([1; -10; 5; -2])), uint64 (5))
764%!assert (max (int64 ([1, 4, 2, 3])), int64 (4))
765%!assert (max (int64 ([1; -10; 5; -2])), int64 (5))
766## Sparse double values
767%!assert (max (sparse ([1, 4, 2, 3])), sparse (4))
768%!assert (max (sparse ([1; -10; 5; -2])), sparse(5))
769%!assert (max (sparse ([4, 2i 4.999; -2, 2, 3+4i])), sparse ([4, 2i, 3+4i]))
770
771## Test dimension argument
772%!test
773%! x = reshape (1:8, [2,2,2]);
774%! assert (min (x, [], 1), reshape ([1, 3, 5, 7], [1,2,2]));
775%! assert (min (x, [], 2), reshape ([1, 2, 5, 6], [2,1,2]));
776%! [y, i] = min (x, [], 3);
777%! assert (ndims (y), 2);
778%! assert (y, [1, 3; 2, 4]);
779%! assert (ndims (i), 2);
780%! assert (i, [1, 1; 1, 1]);
781
782## Test 2-output forms for various arg types
783## Special routines for char arrays
784%!test
785%! [y, i] = max (["abc", "ABC"]);
786%! assert (y, 99);
787%! assert (i, 3);
788## Special routines for logical arrays
789%!test
790%! x = logical ([0 0 1 0]);
791%! [y, i] = max (x);
792%! assert (y, true);
793%! assert (i, 3);
794## Special handling of ranges
795%!test
796%! rng = 1:2:10;
797%! [y, i] = max (rng);
798%! assert (y, 9);
799%! assert (i, 5);
800%! rng = 10:-2:1;
801%! [y, i] = max (rng);
802%! assert (y, 10);
803%! assert (i, 1);
804
805## Test 2-input calling form for various arg types
806## Test generic double class
807%!test
808%! x = [1, 2, 3, 4]; y = fliplr (x);
809%! assert (max (x, y), [4 3 3 4]);
810%! assert (max (x, 3), [3 3 3 4]);
811%! assert (max (2, x), [2 2 3 4]);
812%! assert (max (x, 2.1i), [2.1i 2.1i 3 4]);
813## FIXME: Ordering of complex results with equal magnitude is not by phase
814## angle in the 2-input form. Instead, it is in the order in which it
815## appears in the argument list.
816%!test <51307>
817%! x = [1, 2, 3, 4]; y = fliplr (x);
818%! assert (max (x, 2i), [2i 2i 3 4]);
819## Special routines for char arrays
820%!assert (max ("abc", "b"), [98 98 99])
821%!assert (max ("b", "cba"), [99 98 98])
822## Special handling for logical arrays
823%!assert (max ([true false], false), [true false])
824%!assert (max (true, [false false]), [true true])
825## Single values
826%!test
827%! x = single ([1, 2, 3, 4]); y = fliplr (x);
828%! assert (max (x, y), single ([4 3 3 4]));
829%! assert (max (x, 3), single ([3 3 3 4]));
830%! assert (max (2, x), single ([2 2 3 4]));
831%! assert (max (x, 2.1i), single ([2.1i 2.1i 3 4]));
832## Integer values
833%!test
834%! x = uint8 ([1, 2, 3, 4]); y = fliplr (x);
835%! assert (max (x, y), uint8 ([4 3 3 4]));
836%! assert (max (x, 3), uint8 ([3 3 3 4]));
837%! assert (max (2, x), uint8 ([2 2 3 4]));
838%! x = int8 ([1, 2, 3, 4]); y = fliplr (x);
839%! assert (max (x, y), int8 ([4 3 3 4]));
840%! assert (max (x, 3), int8 ([3 3 3 4]));
841%! assert (max (2, x), int8 ([2 2 3 4]));
842%! x = uint16 ([1, 2, 3, 4]); y = fliplr (x);
843%! assert (max (x, y), uint16 ([4 3 3 4]));
844%! assert (max (x, 3), uint16 ([3 3 3 4]));
845%! assert (max (2, x), uint16 ([2 2 3 4]));
846%! x = int16 ([1, 2, 3, 4]); y = fliplr (x);
847%! assert (max (x, y), int16 ([4 3 3 4]));
848%! assert (max (x, 3), int16 ([3 3 3 4]));
849%! assert (max (2, x), int16 ([2 2 3 4]));
850%! x = uint32 ([1, 2, 3, 4]); y = fliplr (x);
851%! assert (max (x, y), uint32 ([4 3 3 4]));
852%! assert (max (x, 3), uint32 ([3 3 3 4]));
853%! assert (max (2, x), uint32 ([2 2 3 4]));
854%! x = int32 ([1, 2, 3, 4]); y = fliplr (x);
855%! assert (max (x, y), int32 ([4 3 3 4]));
856%! assert (max (x, 3), int32 ([3 3 3 4]));
857%! assert (max (2, x), int32 ([2 2 3 4]));
858%! x = uint64 ([1, 2, 3, 4]); y = fliplr (x);
859%! assert (max (x, y), uint64 ([4 3 3 4]));
860%! assert (max (x, 3), uint64 ([3 3 3 4]));
861%! assert (max (2, x), uint64 ([2 2 3 4]));
862%! x = int64 ([1, 2, 3, 4]); y = fliplr (x);
863%! assert (max (x, y), int64 ([4 3 3 4]));
864%! assert (max (x, 3), int64 ([3 3 3 4]));
865%! assert (max (2, x), int64 ([2 2 3 4]));
866## Sparse double values
867%!test
868%! x = sparse ([1, 2, 3, 4]); y = fliplr (x);
869%! assert (max (x, y), sparse ([4 3 3 4]));
870%! assert (max (x, 3), sparse ([3 3 3 4]));
871%! assert (max (2, x), sparse ([2 2 3 4]));
872%! assert (max (x, 2.1i), sparse ([2.1i 2.1i 3 4]));
873
874## Test for bug #40743
875%!assert <*40743> (max (zeros (1,0), ones (1,1)), zeros (1,0))
876%!assert <*40743> (max (sparse (zeros (1,0)), sparse (ones (1,1))),
877%! sparse (zeros (1,0)))
878
879%!error max ()
880%!error max (1, 2, 3, 4)
881%!error <DIM must be a valid dimension> max ([1 2; 3 4], [], -3)
882%!warning <second argument is ignored> max ([1 2 3 4], 2, 2);
883%!error <wrong type argument 'cell'> max ({1 2 3 4})
884%!error <cannot compute max \‍(cell, scalar\‍)> max ({1, 2, 3}, 2)
885
886*/
887
888template <typename ArrayType>
891 int nargout, int dim, bool ismin)
892{
893 octave_value_list retval (nargout > 1 ? 2 : 1);
894 ArrayType array = octave_value_extract<ArrayType> (arg);
895
896 if (nargout <= 1)
897 {
898 if (ismin)
899 retval(0) = array.cummin (dim);
900 else
901 retval(0) = array.cummax (dim);
902 }
903 else
904 {
905 retval.resize (2);
907 if (ismin)
908 retval(0) = array.cummin (idx, dim);
909 else
910 retval(0) = array.cummax (idx, dim);
911
912 retval(1) = octave_value (idx, true, true);
913 }
914
915 return retval;
916}
917
920 int nargout, bool ismin)
921{
922 int nargin = args.length ();
923
924 if (nargin < 1 || nargin > 2)
925 print_usage ();
926
927 const char *func = (ismin ? "cummin" : "cummax");
928
929 octave_value arg = args(0);
930 int dim = -1;
931 if (nargin == 2)
932 {
933 dim = args(1).int_value (true) - 1;
934
935 if (dim < 0)
936 error ("%s: DIM must be a valid dimension", func);
937 }
938
939 octave_value_list retval;
940
941 switch (arg.builtin_type ())
942 {
943 case btyp_double:
944 retval = do_cumminmax_red_op<NDArray> (arg, nargout, dim, ismin);
945 break;
946
947 case btyp_complex:
948 retval = do_cumminmax_red_op<ComplexNDArray> (arg, nargout, dim,
949 ismin);
950 break;
951
952 case btyp_float:
953 retval = do_cumminmax_red_op<FloatNDArray> (arg, nargout, dim, ismin);
954 break;
955
957 retval = do_cumminmax_red_op<FloatComplexNDArray> (arg, nargout, dim,
958 ismin);
959 break;
960
961#define MAKE_INT_BRANCH(X) \
962 case btyp_ ## X: \
963 retval = do_cumminmax_red_op<X ## NDArray> (arg, nargout, dim, ismin); \
964 break;
965
966 MAKE_INT_BRANCH (int8);
967 MAKE_INT_BRANCH (int16);
968 MAKE_INT_BRANCH (int32);
969 MAKE_INT_BRANCH (int64);
970 MAKE_INT_BRANCH (uint8);
971 MAKE_INT_BRANCH (uint16);
972 MAKE_INT_BRANCH (uint32);
973 MAKE_INT_BRANCH (uint64);
974
975#undef MAKE_INT_BRANCH
976
977 case btyp_bool:
978 {
979 retval = do_cumminmax_red_op<int8NDArray> (arg, nargout, dim,
980 ismin);
981 if (retval.length () > 0)
982 retval(0) = retval(0).bool_array_value ();
983 }
984 break;
985
986 default:
987 err_wrong_type_arg (func, arg);
988 }
989
990 return retval;
991}
992
993DEFUN (cummin, args, nargout,
994 doc: /* -*- texinfo -*-
995@deftypefn {} {} cummin (@var{x})
996@deftypefnx {} {} cummin (@var{x}, @var{dim})
997@deftypefnx {} {[@var{w}, @var{iw}] =} cummin (@var{x})
998Return the cumulative minimum values along dimension @var{dim}.
999
1000If @var{dim} is unspecified it defaults to column-wise operation. For
1001example:
1002
1003@example
1004@group
1005cummin ([5 4 6 2 3 1])
1006 @result{} 5 4 4 2 2 1
1007@end group
1008@end example
1009
1010If called with two output arguments the index of the minimum value is also
1011returned.
1012
1013@example
1014@group
1015[w, iw] = cummin ([5 4 6 2 3 1])
1016@result{}
1017w = 5 4 4 2 2 1
1018iw = 1 2 2 4 4 6
1019@end group
1020@end example
1021
1022@seealso{cummax, min, max}
1023@end deftypefn */)
1024{
1025 return do_cumminmax_body (args, nargout, true);
1026}
1027
1028/*
1029%!assert (cummin ([1, 4, 2, 3]), [1 1 1 1])
1030%!assert (cummin ([1; -10; 5; -2]), [1; -10; -10; -10])
1031%!assert (cummin ([4, i; -2, 2]), [4, i; -2, i])
1032%!assert (cummin ([1 2; NaN 1], 2), [1 1; NaN 1])
1033
1034%!test
1035%! x = reshape (1:8, [2,2,2]);
1036%! assert (cummin (x, 1), reshape ([1 1 3 3 5 5 7 7], [2,2,2]));
1037%! assert (cummin (x, 2), reshape ([1 2 1 2 5 6 5 6], [2,2,2]));
1038%! [w, iw] = cummin (x, 3);
1039%! assert (ndims (w), 3);
1040%! assert (w, repmat ([1 3; 2 4], [1 1 2]));
1041%! assert (ndims (iw), 3);
1042%! assert (iw, ones (2,2,2));
1043
1044%!error cummin ()
1045%!error cummin (1, 2, 3)
1046*/
1047
1048DEFUN (cummax, args, nargout,
1049 doc: /* -*- texinfo -*-
1050@deftypefn {} {} cummax (@var{x})
1051@deftypefnx {} {} cummax (@var{x}, @var{dim})
1052@deftypefnx {} {[@var{w}, @var{iw}] =} cummax (@dots{})
1053Return the cumulative maximum values along dimension @var{dim}.
1054
1055If @var{dim} is unspecified it defaults to column-wise operation. For
1056example:
1057
1058@example
1059@group
1060cummax ([1 3 2 6 4 5])
1061 @result{} 1 3 3 6 6 6
1062@end group
1063@end example
1064
1065If called with two output arguments the index of the maximum value is also
1066returned.
1067
1068@example
1069@group
1070[w, iw] = cummax ([1 3 2 6 4 5])
1071@result{}
1072w = 1 3 3 6 6 6
1073iw = 1 2 2 4 4 4
1074@end group
1075@end example
1076
1077@seealso{cummin, max, min}
1078@end deftypefn */)
1079{
1080 return do_cumminmax_body (args, nargout, false);
1081}
1082
1083/*
1084%!assert (cummax ([1, 4, 2, 3]), [1 4 4 4])
1085%!assert (cummax ([1; -10; 5; -2]), [1; 1; 5; 5])
1086%!assert (cummax ([4, i 4.9, -2, 2, 3+4i]), [4, 4, 4.9, 4.9, 4.9, 3+4i])
1087%!assert (cummax ([1 NaN 0; NaN NaN 1], 2), [1 1 1; NaN NaN 1])
1088
1089%!test
1090%! x = reshape (8:-1:1, [2,2,2]);
1091%! assert (cummax (x, 1), reshape ([8 8 6 6 4 4 2 2], [2,2,2]));
1092%! assert (cummax (x, 2), reshape ([8 7 8 7 4 3 4 3], [2,2,2]));
1093%! [w, iw] = cummax (x, 3);
1094%! assert (ndims (w), 3);
1095%! assert (w, repmat ([8 6; 7 5], [1 1 2]));
1096%! assert (ndims (iw), 3);
1097%! assert (iw, ones (2,2,2));
1098
1099%!error cummax ()
1100%!error cummax (1, 2, 3)
1101*/
1102
1103OCTAVE_NAMESPACE_END
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:207
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:411
bool isempty(void) const
Size of the specified dimension.
Definition: Array.h:607
OCTAVE_API boolNDArray any(int dim=-1) const
Definition: boolNDArray.cc:67
OCTAVE_API boolNDArray all(int dim=-1) const
Definition: boolNDArray.cc:61
OCTAVE_API charNDArray max(int dim=-1) const
Definition: chNDArray.cc:142
OCTAVE_API charNDArray min(int dim=-1) const
Definition: chNDArray.cc:154
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: ovl.h:117
octave_idx_type length(void) const
Definition: ovl.h:113
boolNDArray bool_array_value(bool warn=false) const
Definition: ov.h:936
bool issparse(void) const
Definition: ov.h:798
builtin_type_t builtin_type(void) const
Definition: ov.h:735
bool is_scalar_type(void) const
Definition: ov.h:789
octave::range< double > range_value(void) const
Definition: ov.h:1030
bool is_range(void) const
Definition: ov.h:691
std::string type_name(void) const
Definition: ov.h:1449
OCTINTERP_API 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:1055
void error(const char *fmt,...)
Definition: error.cc:980
void err_wrong_type_arg(const char *name, const char *s)
Definition: errwarn.cc:166
F77_RET_T const F77_DBLE * x
static OCTAVE_NAMESPACE_BEGIN octave_value_list do_minmax_red_op(const octave_value &arg, int nargout, int dim, bool ismin)
Definition: max.cc:51
static octave_value_list do_minmax_body(const octave_value_list &args, int nargout, bool ismin)
Definition: max.cc:241
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)
static octave_value_list do_cumminmax_red_op(const octave_value &arg, int nargout, int dim, bool ismin)
Definition: max.cc:890
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
static octave_value_list do_cumminmax_body(const octave_value_list &args, int nargout, bool ismin)
Definition: max.cc:919
static octave_value do_minmax_bin_op(const octave_value &argx, const octave_value &argy, bool ismin)
Definition: max.cc:159
class OCTAVE_API NDArray
Definition: mx-fwd.h:38
class OCTAVE_API range
Definition: range-fwd.h:33
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:65
builtin_type_t
Definition: ov-base.h:75
@ btyp_float_complex
Definition: ov-base.h:79
@ btyp_double
Definition: ov-base.h:76
@ btyp_float
Definition: ov-base.h:77
@ btyp_bool
Definition: ov-base.h:88
@ btyp_char
Definition: ov-base.h:89
@ btyp_complex
Definition: ov-base.h:78
charNDArray octave_value_extract< charNDArray >(const octave_value &v)
Definition: ov.h:1936