Mercurial > octave
diff src/DLD-FUNCTIONS/max.cc @ 9790:a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Mon, 09 Nov 2009 13:09:49 +0100 |
parents | b4fdfee405b5 |
children | 6e425f6be618 |
line wrap: on
line diff
--- a/src/DLD-FUNCTIONS/max.cc Mon Nov 09 10:21:31 2009 +0100 +++ b/src/DLD-FUNCTIONS/max.cc Mon Nov 09 13:09:49 2009 +0100 @@ -42,646 +42,236 @@ #include "ov-re-sparse.h" #include "ov-cx-sparse.h" -#define MINMAX_DOUBLE_SBODY(FCN) \ -{ \ - if (nargout == 1 || nargout == 0) \ - { \ - if (arg1.is_real_type ()) \ - { \ - NDArray m = arg1.array_value (); \ - \ - if (! error_state) \ - { \ - NDArray n = m. FCN (dim); \ - retval(0) = n; \ - } \ - } \ - else if (arg1.is_complex_type ()) \ - { \ - ComplexNDArray m = arg1.complex_array_value (); \ - \ - if (! error_state) \ - { \ - ComplexNDArray n = m. FCN (dim); \ - retval(0) = n; \ - } \ - } \ - else \ - gripe_wrong_type_arg (#FCN, arg1); \ - } \ - else if (nargout == 2) \ - { \ - Array<octave_idx_type> index; \ - \ - if (arg1.is_real_type ()) \ - { \ - NDArray m = arg1.array_value (); \ - \ - if (! error_state) \ - { \ - NDArray n = m. FCN (index, dim); \ - retval(0) = n; \ - } \ - } \ - else if (arg1.is_complex_type ()) \ - { \ - ComplexNDArray m = arg1.complex_array_value (); \ - \ - if (! error_state) \ - { \ - ComplexNDArray n = m. FCN (index, dim); \ - retval(0) = n; \ - } \ - } \ - else \ - gripe_wrong_type_arg (#FCN, arg1); \ - \ - octave_idx_type len = index.numel (); \ - \ - if (len > 0) \ - retval(1) = octave_value (index, true, true); \ - else \ - retval(1) = NDArray (); \ - } \ +template <class ArrayType> +static octave_value_list +do_minmax_red_op (const octave_value& arg, + int nargout, int dim, bool ismin) +{ + octave_value_list retval; + ArrayType array = octave_value_extract<ArrayType> (arg); + + if (error_state) + return retval; + + if (nargout == 2) + { + retval.resize (2); + Array<octave_idx_type> idx; + if (ismin) + retval(0) = array.min (idx, dim); + else + retval(0) = array.max (idx, dim); + + retval(1) = octave_value (idx, true, true); + } + else + { + if (ismin) + retval(0) = array.min (dim); + else + retval(0) = array.max (dim); + } + + return retval; } -#define MINMAX_DOUBLE_BODY(FCN) \ -{ \ - bool single_arg = (nargin == 1) || (arg2.is_empty() && nargin == 3); \ - if (single_arg) \ - MINMAX_DOUBLE_SBODY (FCN) \ - else \ - { \ - int arg1_is_scalar = arg1.is_scalar_type (); \ - int arg2_is_scalar = arg2.is_scalar_type (); \ - \ - int arg1_is_complex = arg1.is_complex_type (); \ - int arg2_is_complex = arg2.is_complex_type (); \ - \ - if (arg1_is_scalar) \ - { \ - if (arg1_is_complex || arg2_is_complex) \ - { \ - Complex c1 = arg1.complex_value (); \ - ComplexNDArray m2 = arg2.complex_array_value (); \ - if (! error_state) \ - { \ - ComplexNDArray result = FCN (c1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - else \ - { \ - double d1 = arg1.double_value (); \ - NDArray m2 = arg2.array_value (); \ - \ - if (! error_state) \ - { \ - NDArray result = FCN (d1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - else if (arg2_is_scalar) \ - { \ - if (arg1_is_complex || arg2_is_complex) \ - { \ - ComplexNDArray m1 = arg1.complex_array_value (); \ - \ - if (! error_state) \ - { \ - Complex c2 = arg2.complex_value (); \ - ComplexNDArray result = FCN (m1, c2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - else \ - { \ - NDArray m1 = arg1.array_value (); \ - \ - if (! error_state) \ - { \ - double d2 = arg2.double_value (); \ - NDArray result = FCN (m1, d2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - else \ - { \ - if (arg1_is_complex || arg2_is_complex) \ - { \ - ComplexNDArray m1 = arg1.complex_array_value (); \ - \ - if (! error_state) \ - { \ - ComplexNDArray m2 = arg2.complex_array_value (); \ - \ - if (! error_state) \ - { \ - ComplexNDArray result = FCN (m1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - else \ - { \ - NDArray m1 = arg1.array_value (); \ - \ - if (! error_state) \ - { \ - NDArray m2 = arg2.array_value (); \ - \ - if (! error_state) \ - { \ - NDArray result = FCN (m1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - } \ - } \ -} +template <class ArrayType> +static octave_value +do_minmax_bin_op (const octave_value& argx, const octave_value& argy, + bool ismin) +{ + typedef typename ArrayType::element_type ScalarType; + + octave_value retval; + + if (argx.is_scalar_type () == 1) + { + ScalarType x = octave_value_extract<ScalarType> (argx); + ArrayType y = octave_value_extract<ArrayType> (argy); -#define MINMAX_SINGLE_SBODY(FCN) \ -{ \ - if (nargout == 1 || nargout == 0) \ - { \ - if (arg1.is_real_type ()) \ - { \ - FloatNDArray m = arg1.float_array_value (); \ - \ - if (! error_state) \ - { \ - FloatNDArray n = m. FCN (dim); \ - retval(0) = n; \ - } \ - } \ - else if (arg1.is_complex_type ()) \ - { \ - FloatComplexNDArray m = arg1.float_complex_array_value (); \ - \ - if (! error_state) \ - { \ - FloatComplexNDArray n = m. FCN (dim); \ - retval(0) = n; \ - } \ - } \ - else \ - gripe_wrong_type_arg (#FCN, arg1); \ - } \ - else if (nargout == 2) \ - { \ - Array<octave_idx_type> index; \ - \ - if (arg1.is_real_type ()) \ - { \ - FloatNDArray m = arg1.float_array_value (); \ - \ - if (! error_state) \ - { \ - FloatNDArray n = m. FCN (index, dim); \ - retval(0) = n; \ - } \ - } \ - else if (arg1.is_complex_type ()) \ - { \ - FloatComplexNDArray m = arg1.float_complex_array_value (); \ - \ - if (! error_state) \ - { \ - FloatComplexNDArray n = m. FCN (index, dim); \ - retval(0) = n; \ - } \ - } \ - else \ - gripe_wrong_type_arg (#FCN, arg1); \ - \ - octave_idx_type len = index.numel (); \ - \ - if (len > 0) \ - retval(1) = octave_value (index, true, true); \ - else \ - retval(1) = NDArray (); \ - } \ + if (error_state) + ; + else if (ismin) + retval = min (x, y); + else + retval = max (x, y); + } + else if (argy.is_scalar_type () == 1) + { + ArrayType x = octave_value_extract<ArrayType> (argx); + ScalarType y = octave_value_extract<ScalarType> (argy); + + if (error_state) + ; + else if (ismin) + retval = min (x, y); + else + retval = max (x, y); + } + else + { + ArrayType x = octave_value_extract<ArrayType> (argx); + ArrayType y = octave_value_extract<ArrayType> (argy); + + if (error_state) + ; + else if (ismin) + retval = min (x, y); + else + retval = max (x, y); + } + + return retval; } -#define MINMAX_SINGLE_BODY(FCN) \ -{ \ - bool single_arg = (nargin == 1) || (arg2.is_empty() && nargin == 3); \ - if (single_arg) \ - MINMAX_SINGLE_SBODY(FCN) \ - else \ - { \ - int arg1_is_scalar = arg1.is_scalar_type (); \ - int arg2_is_scalar = arg2.is_scalar_type (); \ - \ - int arg1_is_complex = arg1.is_complex_type (); \ - int arg2_is_complex = arg2.is_complex_type (); \ - \ - if (arg1_is_scalar) \ - { \ - if (arg1_is_complex || arg2_is_complex) \ - { \ - FloatComplex c1 = arg1.float_complex_value (); \ - FloatComplexNDArray m2 = arg2.float_complex_array_value (); \ - if (! error_state) \ - { \ - FloatComplexNDArray result = FCN (c1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - else \ - { \ - float d1 = arg1.float_value (); \ - FloatNDArray m2 = arg2.float_array_value (); \ - \ - if (! error_state) \ - { \ - FloatNDArray result = FCN (d1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - else if (arg2_is_scalar) \ - { \ - if (arg1_is_complex || arg2_is_complex) \ - { \ - FloatComplexNDArray m1 = arg1.float_complex_array_value (); \ - \ - if (! error_state) \ - { \ - FloatComplex c2 = arg2.float_complex_value (); \ - FloatComplexNDArray result = FCN (m1, c2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - else \ - { \ - FloatNDArray m1 = arg1.float_array_value (); \ - \ - if (! error_state) \ - { \ - float d2 = arg2.float_value (); \ - FloatNDArray result = FCN (m1, d2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - else \ - { \ - if (arg1_is_complex || arg2_is_complex) \ - { \ - FloatComplexNDArray m1 = arg1.float_complex_array_value (); \ - \ - if (! error_state) \ - { \ - FloatComplexNDArray m2 = arg2.float_complex_array_value (); \ - \ - if (! error_state) \ - { \ - FloatComplexNDArray result = FCN (m1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - else \ - { \ - FloatNDArray m1 = arg1.float_array_value (); \ - \ - if (! error_state) \ - { \ - FloatNDArray m2 = arg2.float_array_value (); \ - \ - if (! error_state) \ - { \ - FloatNDArray result = FCN (m1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - } \ - } \ -} +static octave_value_list +do_minmax_body (const octave_value_list& args, + int nargout, bool ismin) +{ + octave_value_list retval; + + const char *func = ismin ? "min" : "max"; + + int nargin = args.length (); -#define MINMAX_INT_SBODY(FCN, TYP) \ -{ \ - if (nargout == 1 || nargout == 0) \ - { \ - TYP ## NDArray m = arg1. TYP ## _array_value (); \ - \ - if (! error_state) \ - { \ - TYP ## NDArray n = m. FCN (dim); \ - retval(0) = n; \ - } \ - } \ - else if (nargout == 2) \ - { \ - Array<octave_idx_type> index; \ - \ - TYP ## NDArray m = arg1. TYP ## _array_value (); \ - \ - if (! error_state) \ - { \ - TYP ## NDArray n = m. FCN (index, dim); \ - retval(0) = n; \ - } \ - \ - octave_idx_type len = index.numel (); \ - \ - if (len > 0) \ - retval(1) = octave_value (index, true, true); \ - else \ - retval(1) = NDArray (); \ - } \ -} + if (nargin == 3 || nargin == 1) + { + octave_value arg = args(0); + int dim = -1; + if (nargin == 3) + { + dim = args(2).int_value (true) - 1; + if (error_state || dim < 0) + { + error ("%s: invalid dimension", func); + return retval; + } -#define MINMAX_INT_BODY(FCN, TYP) \ - { \ - bool single_arg = (nargin == 1) || (arg2.is_empty() && nargin == 3); \ - if (single_arg) \ - MINMAX_INT_SBODY (FCN, TYP) \ - else \ - { \ - int arg1_is_scalar = arg1.is_scalar_type (); \ - int arg2_is_scalar = arg2.is_scalar_type (); \ - \ - if (arg1_is_scalar) \ - { \ - octave_ ## TYP d1 = arg1. TYP ## _scalar_value (); \ - TYP ## NDArray m2 = arg2. TYP ## _array_value (); \ - \ - if (! error_state) \ - { \ - TYP ## NDArray result = FCN (d1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - else if (arg2_is_scalar) \ - { \ - TYP ## NDArray m1 = arg1. TYP ## _array_value (); \ - \ - if (! error_state) \ - { \ - octave_ ## TYP d2 = arg2. TYP ## _scalar_value (); \ - TYP ## NDArray result = FCN (m1, d2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - else \ - { \ - TYP ## NDArray m1 = arg1. TYP ## _array_value (); \ - \ - if (! error_state) \ - { \ - TYP ## NDArray m2 = arg2. TYP ## _array_value (); \ - \ - if (! error_state) \ - { \ - TYP ## NDArray result = FCN (m1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - } \ -} + if (! args(1).is_empty ()) + warning ("%s: second argument is ignored"); + } -#define MINMAX_SPARSE_BODY(FCN) \ -{ \ - bool single_arg = (nargin == 1) || arg2.is_empty(); \ - \ - if (single_arg && (nargout == 1 || nargout == 0)) \ - { \ - if (arg1.is_real_type ()) \ - retval(0) = arg1.sparse_matrix_value () .FCN (dim); \ - else if (arg1.is_complex_type ()) \ - retval(0) = arg1.sparse_complex_matrix_value () .FCN (dim); \ - else \ - gripe_wrong_type_arg (#FCN, arg1); \ - } \ - else if (single_arg && nargout == 2) \ - { \ - Array2<octave_idx_type> index; \ - \ - if (arg1.is_real_type ()) \ - retval(0) = arg1.sparse_matrix_value () .FCN (index, dim); \ - else if (arg1.is_complex_type ()) \ - retval(0) = arg1.sparse_complex_matrix_value () .FCN (index, dim); \ - else \ - gripe_wrong_type_arg (#FCN, arg1); \ - \ - octave_idx_type len = index.numel (); \ - \ - if (len > 0) \ - retval(1) = octave_value (index, true, true); \ - else \ - retval(1) = NDArray (); \ - } \ - else \ - { \ - int arg1_is_scalar = arg1.is_scalar_type (); \ - int arg2_is_scalar = arg2.is_scalar_type (); \ - \ - int arg1_is_complex = arg1.is_complex_type (); \ - int arg2_is_complex = arg2.is_complex_type (); \ - \ - if (arg1_is_scalar) \ - { \ - if (arg1_is_complex || arg2_is_complex) \ - { \ - Complex c1 = arg1.complex_value (); \ - \ - SparseComplexMatrix m2 = arg2.sparse_complex_matrix_value (); \ - \ - if (! error_state) \ - { \ - SparseComplexMatrix result = FCN (c1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - else \ - { \ - double d1 = arg1.double_value (); \ - SparseMatrix m2 = arg2.sparse_matrix_value (); \ - \ - if (! error_state) \ - { \ - SparseMatrix result = FCN (d1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - else if (arg2_is_scalar) \ - { \ - if (arg1_is_complex || arg2_is_complex) \ - { \ - SparseComplexMatrix m1 = arg1.sparse_complex_matrix_value (); \ - \ - if (! error_state) \ - { \ - Complex c2 = arg2.complex_value (); \ - SparseComplexMatrix result = FCN (m1, c2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - else \ - { \ - SparseMatrix m1 = arg1.sparse_matrix_value (); \ - \ - if (! error_state) \ - { \ - double d2 = arg2.double_value (); \ - SparseMatrix result = FCN (m1, d2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - else \ - { \ - if (arg1_is_complex || arg2_is_complex) \ - { \ - SparseComplexMatrix m1 = arg1.sparse_complex_matrix_value (); \ - \ - if (! error_state) \ - { \ - SparseComplexMatrix m2 = arg2.sparse_complex_matrix_value (); \ - \ - if (! error_state) \ - { \ - SparseComplexMatrix result = FCN (m1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - else \ - { \ - SparseMatrix m1 = arg1.sparse_matrix_value (); \ - \ - if (! error_state) \ - { \ - SparseMatrix m2 = arg2.sparse_matrix_value (); \ - \ - if (! error_state) \ - { \ - SparseMatrix result = FCN (m1, m2); \ - if (! error_state) \ - retval(0) = result; \ - } \ - } \ - } \ - } \ - } \ + switch (arg.builtin_type ()) + { + case btyp_double: + { + if (arg.is_range () && (dim == -1 || dim == 1)) + { + Range range = arg.range_value (); + if (range.nelem () == 0) + { + retval(0) = arg; + if (nargout > 1) + retval(1) = arg; + } + else if (ismin) + { + retval(0) = range.min (); + if (nargout > 1) + retval(1) = static_cast<double> (range.inc () < 0 ? range.nelem () : 1); + } + else + { + retval(0) = range.max (); + if (nargout > 1) + retval(1) = static_cast<double> (range.inc () >= 0 ? range.nelem () : 1); + } + } + else if (arg.is_sparse_type ()) + retval = do_minmax_red_op<SparseMatrix> (arg, nargout, dim, ismin); + else + retval = do_minmax_red_op<NDArray> (arg, nargout, dim, ismin); + break; + } + case btyp_complex: + { + if (arg.is_sparse_type ()) + retval = do_minmax_red_op<SparseComplexMatrix> (arg, nargout, dim, ismin); + else + retval = do_minmax_red_op<ComplexNDArray> (arg, nargout, dim, ismin); + break; + } + case btyp_float: + retval = do_minmax_red_op<FloatNDArray> (arg, nargout, dim, ismin); + break; + case btyp_float_complex: + retval = do_minmax_red_op<FloatComplexNDArray> (arg, nargout, dim, ismin); + break; +#define MAKE_INT_BRANCH(X) \ + case btyp_ ## X: \ + retval = do_minmax_red_op<X ## NDArray> (arg, nargout, dim, ismin); \ + break; + MAKE_INT_BRANCH (int8); + MAKE_INT_BRANCH (int16); + MAKE_INT_BRANCH (int32); + MAKE_INT_BRANCH (int64); + MAKE_INT_BRANCH (uint8); + MAKE_INT_BRANCH (uint16); + MAKE_INT_BRANCH (uint32); + MAKE_INT_BRANCH (uint64); +#undef MAKE_INT_BRANCH + default: + gripe_wrong_type_arg (func, arg); + } + } + else if (nargin == 2) + { + octave_value argx = args(0), argy = args(1); + builtin_type_t xtyp = argx.builtin_type (), ytyp = argy.builtin_type (); + builtin_type_t rtyp = btyp_mixed_numeric (xtyp, ytyp); + + switch (rtyp) + { + case btyp_double: + { + if ((argx.is_sparse_type () + && (argy.is_sparse_type () || argy.is_scalar_type ())) + || (argy.is_sparse_type () && argx.is_scalar_type ())) + retval = do_minmax_bin_op<SparseMatrix> (argx, argy, ismin); + else + retval = do_minmax_bin_op<NDArray> (argx, argy, ismin); + break; + } + case btyp_complex: + { + if ((argx.is_sparse_type () + && (argy.is_sparse_type () || argy.is_scalar_type ())) + || (argy.is_sparse_type () && argx.is_scalar_type ())) + retval = do_minmax_bin_op<SparseComplexMatrix> (argx, argy, ismin); + else + retval = do_minmax_bin_op<ComplexNDArray> (argx, argy, ismin); + break; + } + case btyp_float: + retval = do_minmax_bin_op<FloatNDArray> (argx, argy, ismin); + break; + case btyp_float_complex: + retval = do_minmax_bin_op<FloatComplexNDArray> (argx, argy, ismin); + break; +#define MAKE_INT_BRANCH(X) \ + case btyp_ ## X: \ + retval = do_minmax_bin_op<X ## NDArray> (argx, argy, ismin); \ + break; + MAKE_INT_BRANCH (int8); + MAKE_INT_BRANCH (int16); + MAKE_INT_BRANCH (int32); + MAKE_INT_BRANCH (int64); + MAKE_INT_BRANCH (uint8); + MAKE_INT_BRANCH (uint16); + MAKE_INT_BRANCH (uint32); + MAKE_INT_BRANCH (uint64); +#undef MAKE_INT_BRANCH + default: + error ("%s: cannot compute %s (%s, %s)", func, func, + argx.type_name ().c_str (), argy.type_name ().c_str ()); + } + } + else + print_usage (); + + return retval; } - -#define MINMAX_BODY(FCN) \ - \ - octave_value_list retval; \ - \ - int nargin = args.length (); \ - \ - if (nargin < 1 || nargin > 3 || nargout > 2) \ - { \ - print_usage (); \ - return retval; \ - } \ - \ - octave_value arg1; \ - octave_value arg2; \ - octave_value arg3; \ - \ - switch (nargin) \ - { \ - case 3: \ - arg3 = args(2); \ - \ - case 2: \ - arg2 = args(1); \ - \ - case 1: \ - arg1 = args(0); \ - break; \ - \ - default: \ - panic_impossible (); \ - break; \ - } \ - \ - int dim; \ - dim_vector dv = arg1.dims (); \ - if (error_state) \ - { \ - gripe_wrong_type_arg (#FCN, arg1); \ - return retval; \ - } \ - \ - if (nargin == 3) \ - { \ - dim = arg3.nint_value () - 1; \ - if (dim < 0 || dim >= dv.length ()) \ - { \ - error ("%s: invalid dimension", #FCN); \ - return retval; \ - } \ - } \ - else \ - { \ - dim = 0; \ - while ((dim < dv.length ()) && (dv (dim) <= 1)) \ - dim++; \ - if (dim == dv.length ()) \ - dim = 0; \ - } \ - \ - if (arg1.is_integer_type ()) \ - { \ - if (arg1.is_uint8_type ()) \ - MINMAX_INT_BODY (FCN, uint8) \ - else if (arg1.is_uint16_type ()) \ - MINMAX_INT_BODY (FCN, uint16) \ - else if (arg1.is_uint32_type ()) \ - MINMAX_INT_BODY (FCN, uint32) \ - else if (arg1.is_uint64_type ()) \ - MINMAX_INT_BODY (FCN, uint64) \ - else if (arg1.is_int8_type ()) \ - MINMAX_INT_BODY (FCN, int8) \ - else if (arg1.is_int16_type ()) \ - MINMAX_INT_BODY (FCN, int16) \ - else if (arg1.is_int32_type ()) \ - MINMAX_INT_BODY (FCN, int32) \ - else if (arg1.is_int64_type ()) \ - MINMAX_INT_BODY (FCN, int64) \ - } \ - else if (arg1.is_sparse_type ()) \ - MINMAX_SPARSE_BODY (FCN) \ - else if (arg1.is_single_type ()) \ - MINMAX_SINGLE_BODY (FCN) \ - else \ - MINMAX_DOUBLE_BODY (FCN) \ - \ - return retval; - DEFUN_DLD (min, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {} min (@var{x})\n\ @@ -728,7 +318,7 @@ @seealso{max, cummin, cummax}\n\ @end deftypefn") { - MINMAX_BODY (min); + return do_minmax_body (args, nargout, true); } /* @@ -804,7 +394,7 @@ @seealso{min, cummax, cummin}\n\ @end deftypefn") { - MINMAX_BODY (max); + return do_minmax_body (args, nargout, false); } /* @@ -835,86 +425,99 @@ */ -#define CUMMINMAX_BODY(FCN) \ - \ - octave_value_list retval; \ - \ - int nargin = args.length (); \ - \ - if (nargin < 1 || nargin > 2 || nargout > 2) \ - { \ - print_usage (); \ - return retval; \ - } \ - \ - octave_value arg1; \ - octave_value arg2; \ - \ - switch (nargin) \ - { \ - case 2: \ - arg2 = args(1); \ - \ - case 1: \ - arg1 = args(0); \ - break; \ - \ - default: \ - panic_impossible (); \ - break; \ - } \ - \ - int dim; \ - dim_vector dv = arg1.dims (); \ - if (error_state) \ - { \ - gripe_wrong_type_arg (#FCN, arg1); \ - return retval; \ - } \ - \ - if (nargin == 2) \ - { \ - dim = arg2.nint_value () - 1; \ - if (dim < 0 || dim >= dv.length ()) \ - { \ - error ("%s: invalid dimension", #FCN); \ - return retval; \ - } \ - } \ - else \ - { \ - dim = 0; \ - while ((dim < dv.length ()) && (dv (dim) <= 1)) \ - dim++; \ - if (dim == dv.length ()) \ - dim = 0; \ - } \ - \ - if (arg1.is_integer_type ()) \ - { \ - if (arg1.is_uint8_type ()) \ - MINMAX_INT_SBODY (FCN, uint8) \ - else if (arg1.is_uint16_type ()) \ - MINMAX_INT_SBODY (FCN, uint16) \ - else if (arg1.is_uint32_type ()) \ - MINMAX_INT_SBODY (FCN, uint32) \ - else if (arg1.is_uint64_type ()) \ - MINMAX_INT_SBODY (FCN, uint64) \ - else if (arg1.is_int8_type ()) \ - MINMAX_INT_SBODY (FCN, int8) \ - else if (arg1.is_int16_type ()) \ - MINMAX_INT_SBODY (FCN, int16) \ - else if (arg1.is_int32_type ()) \ - MINMAX_INT_SBODY (FCN, int32) \ - else if (arg1.is_int64_type ()) \ - MINMAX_INT_SBODY (FCN, int64) \ - } \ - else if (arg1.is_single_type ()) \ - MINMAX_SINGLE_SBODY (FCN) \ - else \ - MINMAX_DOUBLE_SBODY (FCN) \ - \ - return retval; +template <class ArrayType> +static octave_value_list +do_cumminmax_red_op (const octave_value& arg, + int nargout, int dim, bool ismin) +{ + octave_value_list retval; + ArrayType array = octave_value_extract<ArrayType> (arg); + + if (error_state) + return retval; + + if (nargout == 2) + { + retval.resize (2); + Array<octave_idx_type> idx; + if (ismin) + retval(0) = array.cummin (idx, dim); + else + retval(0) = array.cummax (idx, dim); + + retval(1) = octave_value (idx, true, true); + } + else + { + if (ismin) + retval(0) = array.cummin (dim); + else + retval(0) = array.cummax (dim); + } + + return retval; +} + +static octave_value_list +do_cumminmax_body (const octave_value_list& args, + int nargout, bool ismin) +{ + octave_value_list retval; + + const char *func = ismin ? "cummin" : "cummax"; + + int nargin = args.length (); + + if (nargin == 1 || nargin == 2) + { + octave_value arg = args(0); + int dim = -1; + if (nargin == 2) + { + dim = args(1).int_value (true) - 1; + if (error_state || dim < 0) + { + error ("%s: invalid dimension", func); + return retval; + } + } + + switch (arg.builtin_type ()) + { + case btyp_double: + retval = do_cumminmax_red_op<NDArray> (arg, nargout, dim, ismin); + break; + case btyp_complex: + retval = do_cumminmax_red_op<ComplexNDArray> (arg, nargout, dim, ismin); + break; + case btyp_float: + retval = do_cumminmax_red_op<FloatNDArray> (arg, nargout, dim, ismin); + break; + case btyp_float_complex: + retval = do_cumminmax_red_op<FloatComplexNDArray> (arg, nargout, dim, ismin); + break; +#define MAKE_INT_BRANCH(X) \ + case btyp_ ## X: \ + retval = do_cumminmax_red_op<X ## NDArray> (arg, nargout, dim, ismin); \ + break; + MAKE_INT_BRANCH (int8); + MAKE_INT_BRANCH (int16); + MAKE_INT_BRANCH (int32); + MAKE_INT_BRANCH (int64); + MAKE_INT_BRANCH (uint8); + MAKE_INT_BRANCH (uint16); + MAKE_INT_BRANCH (uint32); + MAKE_INT_BRANCH (uint64); +#undef MAKE_INT_BRANCH + default: + gripe_wrong_type_arg (func, arg); + } + } + else + print_usage (); + + return retval; +} DEFUN_DLD (cummin, args, nargout, "-*- texinfo -*-\n\ @@ -955,7 +558,7 @@ @seealso{cummax, min, max}\n\ @end deftypefn") { - CUMMINMAX_BODY (cummin); + return do_cumminmax_body (args, nargout, true); } DEFUN_DLD (cummax, args, nargout, @@ -996,7 +599,7 @@ @seealso{cummin, max, min}\n\ @end deftypefn") { - CUMMINMAX_BODY (cummax); + return do_cumminmax_body (args, nargout, false); } /*