GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
max.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2025 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
49template <typename ArrayType>
51do_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
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
159do_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
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
241do_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
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
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
441DEFUN (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})
447Find minimum values in the array @var{x}.
448
449For a vector argument, return the minimum value. For a matrix argument,
450return a row vector with the minimum value of each column. For a
451multi-dimensional array, @code{min} operates along the first non-singleton
452dimension.
453
454If the optional third argument @var{dim} is present then operate along
455this dimension. In this case the second argument is ignored and should be
456set to the empty matrix.
457
458For two inputs (@var{x} and @var{y}), return the pairwise minimum according to
459the rules for @ref{Broadcasting}.
460
461Thus,
462
463@example
464min (min (@var{x}))
465@end example
466
467@noindent
468returns the smallest element of the 2-D matrix @var{x}, and
469
470@example
471@group
472min (2:5, pi)
473 @result{} 2.0000 3.0000 3.1416 3.1416
474@end group
475@end example
476
477@noindent
478compares each element of the range @code{2:5} with @code{pi}, and returns a
479row vector of the minimum values.
480
481For complex arguments, the magnitude of the elements are used for
482comparison. If the magnitudes are identical, then the results are ordered
483by phase angle in the range (-pi, pi]. Hence,
484
485@example
486@group
487min ([-1 i 1 -i])
488 @result{} -i
489@end group
490@end example
491
492@noindent
493because all entries have magnitude 1, but -i has the smallest phase angle
494with value -pi/2.
495
496If called with one input and two output arguments, @code{min} also returns
497the 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
663DEFUN (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})
669Find maximum values in the array @var{x}.
670
671For a vector argument, return the maximum value. For a matrix argument,
672return a row vector with the maximum value of each column. For a
673multi-dimensional array, @code{max} operates along the first non-singleton
674dimension.
675
676If the optional third argument @var{dim} is present then operate along
677this dimension. In this case the second argument is ignored and should be
678set to the empty matrix.
679
680For two inputs (@var{x} and @var{y}), return the pairwise maximum according to
681the rules for @ref{Broadcasting}.
682
683Thus,
684
685@example
686max (max (@var{x}))
687@end example
688
689@noindent
690returns the largest element of the 2-D matrix @var{x}, and
691
692@example
693@group
694max (2:5, pi)
695 @result{} 3.1416 3.1416 4.0000 5.0000
696@end group
697@end example
698
699@noindent
700compares each element of the range @code{2:5} with @code{pi}, and returns a
701row vector of the maximum values.
702
703For complex arguments, the magnitude of the elements are used for
704comparison. If the magnitudes are identical, then the results are ordered
705by phase angle in the range (-pi, pi]. Hence,
706
707@example
708@group
709max ([-1 i 1 -i])
710 @result{} -1
711@end group
712@end example
713
714@noindent
715because all entries have magnitude 1, but -1 has the largest phase angle
716with value pi.
717
718If called with one input and two output arguments, @code{max} also returns
719the 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
889template <typename ArrayType>
891do_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
920do_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
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
994DEFUN (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})
999Return the cumulative minimum values along dimension @var{dim}.
1000
1001If @var{dim} is unspecified it defaults to column-wise operation. For
1002example:
1003
1004@example
1005@group
1006cummin ([5 4 6 2 3 1])
1007 @result{} 5 4 4 2 2 1
1008@end group
1009@end example
1010
1011If called with two output arguments the index of the minimum value is also
1012returned.
1013
1014@example
1015@group
1016[M, IM] = cummin ([5 4 6 2 3 1])
1017@result{}
1018M = 5 4 4 2 2 1
1019IM = 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
1049DEFUN (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{})
1054Return the cumulative maximum values along dimension @var{dim}.
1055
1056If @var{dim} is unspecified it defaults to column-wise operation. For
1057example:
1058
1059@example
1060@group
1061cummax ([1 3 2 6 4 5])
1062 @result{} 1 3 3 6 6 6
1063@end group
1064@end example
1065
1066If called with two output arguments the index of the maximum value is also
1067returned.
1068
1069@example
1070@group
1071[w, iw] = cummax ([1 3 2 6 4 5])
1072@result{}
1073M = 1 3 3 6 6 6
1074IM = 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
1104OCTAVE_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
N Dimensional Array with copy-on-write semantics.
Definition Array.h:130
bool isempty() const
Size of the specified dimension.
Definition Array.h:652
octave_idx_type numel() const
Number of elements in the array.
Definition Array.h:418
boolNDArray any(int dim=-1) const
boolNDArray all(int dim=-1) const
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition ovl.h:115
octave_idx_type length() const
Definition ovl.h:111
boolNDArray bool_array_value(bool warn=false) const
Definition ov.h:900
bool is_scalar_type() const
Definition ov.h:744
bool is_range() const
Definition ov.h:646
bool issparse() const
Definition ov.h:753
std::string type_name() const
Definition ov.h:1360
builtin_type_t builtin_type() const
Definition ov.h:690
octave::range< double > range_value() const
Definition ov.h:994
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage()
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:1078
void error(const char *fmt,...)
Definition error.cc:1003
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
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:1755