From octave-maintainers-request at bevo dot che dot wisc dot edu Sun Sep 3 23:30:17 2000 Subject: [PATCH] Expose min/max NaN options to interpreter (3/4) From: Edward Jason Riedy To: octave-maintainers at bevo dot che dot wisc dot edu Date: Sun, 03 Sep 2000 21:30:16 -0700 This is a massive overhaul of src/DLD-FUNCTIONS/minmax.cc. It's slightly cpp-happy. The only advantage to a template-based solution with a similar structure to the current code would be cc-mode-friendliness. It could be re-worked to use a dispatch system similar to the operators', but that would be a good deal of work. Jason src/ChangeLog * DLD-FUNCTIONS/minmax.cc (SM_COMP): Macro added to define scalar- matrix comparisons. (MS_COMP): Same for matrix-scalar. (MM_COMP): Same for matrix-matrix. (min): All helper definitions replaced by calls to the above macros. (max): Ditto. (MINMAX_DISPATCH): Macro to give both DEFUN_DLD (min, ...) and DEFUN_DLD (max, ...) the same bodies. (interpreter's min): Body replaced by call to MINMAX_DISPATCH (min). (interpreter's max): Equivalent change. --- octave.orig/src/DLD-FUNCTIONS/minmax.cc Tue Apr 11 12:02:05 2000 +++ octave.2/src/DLD-FUNCTIONS/minmax.cc Sun Sep 3 16:43:49 2000 at @ -34,244 +34,388 @@ #include "gripes.h" #include "oct-obj.h" -// XXX FIXME XXX -- it would be nice to share code among the min/max -// functions below. - -static Matrix -min (double d, const Matrix& m) -{ - int nr = m.rows (); - int nc = m.columns (); - - Matrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - result (i, j) = xmin (d, m (i, j)); - - return result; -} - -static Matrix -min (const Matrix& m, double d) -{ - int nr = m.rows (); - int nc = m.columns (); - - Matrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - result (i, j) = xmin (m (i, j), d); - - return result; -} - -static ComplexMatrix -min (const Complex& c, const ComplexMatrix& m) -{ - int nr = m.rows (); - int nc = m.columns (); - - ComplexMatrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - result (i, j) = xmin (c, m (i, j)); - - return result; -} - -static ComplexMatrix -min (const ComplexMatrix& m, const Complex& c) -{ - int nr = m.rows (); - int nc = m.columns (); - - ComplexMatrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - result (i, j) = xmin (m (i, j), c); - - return result; -} - -static Matrix -min (const Matrix& a, const Matrix& b) -{ - int nr = a.rows (); - int nc = a.columns (); - if (nr != b.rows () || nc != b.columns ()) - { - error ("two-arg min expecting args of same size"); - return Matrix (); - } - - Matrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - result (i, j) = xmin (a (i, j), b (i, j)); - - return result; -} - -static ComplexMatrix -min (const ComplexMatrix& a, const ComplexMatrix& b) -{ - int nr = a.rows (); - int nc = a.columns (); - if (nr != b.rows () || nc != b.columns ()) - { - error ("two-arg min expecting args of same size"); - return ComplexMatrix (); - } - - ComplexMatrix result (nr, nc); - - for (int j = 0; j < nc; j++) - { - int columns_are_real_only = 1; - for (int i = 0; i < nr; i++) - if (imag (a (i, j)) != 0.0 || imag (b (i, j)) != 0.0) - { - columns_are_real_only = 0; - break; - } - - if (columns_are_real_only) - { - for (int i = 0; i < nr; i++) - result (i, j) = xmin (real (a (i, j)), real (b (i, j))); - } - else - { - for (int i = 0; i < nr; i++) - result (i, j) = xmin (a (i, j), b (i, j)); - } - } - - return result; -} - -static Matrix -max (double d, const Matrix& m) -{ - int nr = m.rows (); - int nc = m.columns (); - - Matrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - result (i, j) = xmax (d, m (i, j)); - - return result; -} - -static Matrix -max (const Matrix& m, double d) -{ - int nr = m.rows (); - int nc = m.columns (); - - Matrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - result (i, j) = xmax (m (i, j), d); - - return result; -} - -static ComplexMatrix -max (const Complex& c, const ComplexMatrix& m) -{ - int nr = m.rows (); - int nc = m.columns (); - - ComplexMatrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - result (i, j) = xmax (c, m (i, j)); - - return result; -} - -static ComplexMatrix -max (const ComplexMatrix& m, const Complex& c) -{ - int nr = m.rows (); - int nc = m.columns (); - - ComplexMatrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - result (i, j) = xmax (m (i, j), c); - - return result; -} - -static Matrix -max (const Matrix& a, const Matrix& b) -{ - int nr = a.rows (); - int nc = a.columns (); - if (nr != b.rows () || nc != b.columns ()) - { - error ("two-arg max expecting args of same size"); - return Matrix (); - } - - Matrix result (nr, nc); - - for (int j = 0; j < nc; j++) - for (int i = 0; i < nr; i++) - result (i, j) = xmax (a (i, j), b (i, j)); - - return result; -} - -static ComplexMatrix -max (const ComplexMatrix& a, const ComplexMatrix& b) -{ - int nr = a.rows (); - int nc = a.columns (); - if (nr != b.rows () || nc != b.columns ()) - { - error ("two-arg max expecting args of same size"); - return ComplexMatrix (); - } - - ComplexMatrix result (nr, nc); - - for (int j = 0; j < nc; j++) - { - int columns_are_real_only = 1; - for (int i = 0; i < nr; i++) - if (imag (a (i, j)) != 0.0 || imag (b (i, j)) != 0.0) - { - columns_are_real_only = 0; - break; - } - - if (columns_are_real_only) - { - for (int i = 0; i < nr; i++) - result (i, j) = xmax (real (a (i, j)), real (b (i, j))); - } - else - { - for (int i = 0; i < nr; i++) - result (i, j) = xmax (a (i, j), b (i, j)); - } - } - - return result; -} +/* + XXX: Re-write each of the XX_COMP macros to define a member + function within an Op class, e.g. + struct Min + { + SM_COMP(double, ComplexMatrix, Min) + ... + }; + would produce + struct Min + { + static void apply (const double d, const ComplexMatrix& m, ...) + { + ... + } + ... + }; + + Then change the MINMAX_DISPATCH macro to a template class. + Instantiate it once with each struct. Then the dispatch + routines just call the appropriate template class. + + That's the more C++-ish way to avoid macros, and it's probably + more debugger- friendly. You could also restructure everything + to fit a framework like the operators one level up (see + ../ov-typeinfo.h and ../ops.h). However, these are meant to be + dynamically loadable, and that framework relies on static + initialization. The two don't play nice on most current (Aug + 2000) systems. It also will begin to resemble an unoptimized + subset of Common Lisp, but that's another story. +*/ + +// Scalar-matrix comparisons + +/* + Note that a good optimizer should hoist the ignore_nan tests out of the + loop. +*/ + +#define SM_COMP(ScalarType, MatrixType, Op) \ +static MatrixType \ +Op (const ScalarType d, const MatrixType& m, \ + const bool ignore_nan = OCTAVE_IGNORE_NAN_DEFAULT) \ +{ \ + const int nr = m.rows (); \ + const int nc = m.columns (); \ + \ + MatrixType result (nr, nc); \ + \ + for (int j = 0; j < nc; j++) \ + for (int i = 0; i < nr; i++) \ + if (ignore_nan) \ + result (i, j) = x ## Op (d, m (i, j)); \ + else \ + result (i, j) = x ## Op ## _nan (d, m (i, j)); \ + \ + return result; \ +} + +SM_COMP(double, Matrix, min) +SM_COMP(double, Matrix, max) + +SM_COMP(Complex, ComplexMatrix, min) +SM_COMP(Complex, ComplexMatrix, max) + +#undef SM_COMP + +// Matrix-scalar comparisons + +#define MS_COMP(ScalarType, MatrixType, Op) \ +static MatrixType \ +Op (const MatrixType& m, const ScalarType d, \ + const bool ignore_nan = OCTAVE_IGNORE_NAN_DEFAULT) \ +{ \ + const int nr = m.rows (); \ + const int nc = m.columns (); \ + \ + MatrixType result (nr, nc); \ + \ + for (int j = 0; j < nc; j++) \ + for (int i = 0; i < nr; i++) \ + if (ignore_nan) \ + result (i, j) = x ## Op (m (i, j), d); \ + else \ + result (i, j) = x ## Op ## _nan (m (i, j), d); \ + \ + return result; \ +} + +MS_COMP(double, Matrix, min) +MS_COMP(double, Matrix, max) + +MS_COMP(Complex, ComplexMatrix, min) +MS_COMP(Complex, ComplexMatrix, max) + +#undef MS_COMP + +// Matrix-matrix comparisons + +#define MM_COMP(Op, MatType) \ +static MatType \ +Op (const MatType& a, const MatType& b, \ + const bool ignore_nan = OCTAVE_IGNORE_NAN_DEFAULT) \ +{ \ + const int nr = a.rows(); \ + int nc = a.columns (); \ + if (nr != b.rows () || nc != b.columns ()) \ + { \ + error ("two-arg min expecting args of same size"); \ + return MatType (); \ + } \ + \ + MatType result (nr, nc); \ + \ + for (int j = 0; j < nc; j++) \ + for (int i = 0; i < nr; i++) \ + if (ignore_nan) \ + result (i, j) = x ## Op (a (i, j), b (i, j)); \ + else \ + result (i, j) = x ## Op ## _nan (a (i, j), b (i, j)); \ + \ + return result; \ +} + +MM_COMP(min, Matrix) +MM_COMP(max, Matrix) + +MM_COMP(min, ComplexMatrix) +MM_COMP(max, ComplexMatrix) + +#undef MM_COMP + +// interpreter routines + +#define MINMAX_DISPATCH(op) do \ +{ \ + octave_value_list retval; \ + \ + int nargin = args.length (); \ + int noptargin = 0; \ + \ + /* Find the optional args at the end of the list */ \ + while (nargin > 0) \ + { \ + if (args(nargin-1).is_numeric_type()) \ + break; \ + --nargin; \ + ++noptargin; \ + } \ + \ + if (nargin < 1 || nargin > 2 || nargout > 2 || noptargin > 1) \ + { \ + print_usage (#op); \ + return retval; \ + } \ + \ + bool ignore_nan = OCTAVE_IGNORE_NAN_DEFAULT; \ + \ + if (noptargin) \ + { \ + /* nargin is the index of the single optarg */ \ + \ + const std::string optarg = args(nargin).string_value(); \ + bool valid_option = false; \ + if (optarg == "ignore-nan") \ + { \ + valid_option = true; \ + ignore_nan = true; \ + } \ + if (optarg == "prefer-nan") \ + { \ + valid_option = true; \ + ignore_nan = false; \ + } \ + \ + if (!valid_option) \ + { \ + print_usage ("min"); \ + return retval; \ + } \ + } \ + \ + octave_value arg1; \ + octave_value arg2; \ + \ + switch (nargin) \ + { \ + case 2: \ + arg2 = args(1); \ + /* Fall through... */ \ + \ + case 1: \ + arg1 = args(0); \ + break; \ + \ + default: \ + panic_impossible (); \ + break; \ + } \ + \ + if (nargin == 1 && (nargout == 1 || nargout == 0)) \ + { \ + if (arg1.is_real_type ()) \ + { \ + Matrix m = arg1.matrix_value (); \ + \ + if (! error_state) \ + { \ + if (m.rows () == 1) \ + retval(0) = m.row_##op (ignore_nan); \ + else \ + retval(0) = m.column_##op (ignore_nan); \ + } \ + } \ + else if (arg1.is_complex_type ()) \ + { \ + ComplexMatrix m = arg1.complex_matrix_value (); \ + \ + if (! error_state) \ + { \ + if (m.rows () == 1) \ + retval(0) = m.row_##op (ignore_nan); \ + else \ + retval(0) = m.column_##op (ignore_nan); \ + } \ + } \ + else \ + gripe_wrong_type_arg (#op, arg1); \ + } \ + else if (nargin == 1 && nargout == 2) \ + { \ + Array index; \ + \ + if (arg1.is_real_type ()) \ + { \ + Matrix m = arg1.matrix_value (); \ + \ + if (! error_state) \ + { \ + retval.resize (2); \ + \ + if (m.rows () == 1) \ + retval(0) = m.row_##op (index, ignore_nan); \ + else \ + retval(0) = m.column_##op (index, ignore_nan); \ + } \ + } \ + else if (arg1.is_complex_type ()) \ + { \ + ComplexMatrix m = arg1.complex_matrix_value (); \ + \ + if (! error_state) \ + { \ + retval.resize (2); \ + \ + if (m.rows () == 1) \ + retval(0) = m.row_##op (index, ignore_nan); \ + else \ + retval(0) = m.column_##op (index, ignore_nan); \ + } \ + } \ + else \ + gripe_wrong_type_arg (#op, arg1); \ + \ + int len = index.length (); \ + \ + if (len > 0) \ + { \ + RowVector idx (len); \ + \ + for (int i = 0; i < len; i++) \ + { \ + int tmp = index.elem (i) + 1; \ + idx.elem (i) = (tmp <= 0) \ + ? octave_NaN : static_cast (tmp); \ + } \ + \ + retval(1) = idx; \ + } \ + } \ + else if (nargin == 2) \ + { \ + 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 (); \ + ComplexMatrix m2 = arg2.complex_matrix_value (); \ + if (! error_state) \ + { \ + ComplexMatrix result = op (c1, m2, ignore_nan); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + else \ + { \ + double d1 = arg1.double_value (); \ + Matrix m2 = arg2.matrix_value (); \ + \ + if (! error_state) \ + { \ + Matrix result = op (d1, m2, ignore_nan); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + } \ + else if (arg2_is_scalar) \ + { \ + if (arg1_is_complex || arg2_is_complex) \ + { \ + ComplexMatrix m1 = arg1.complex_matrix_value (); \ + \ + if (! error_state) \ + { \ + Complex c2 = arg2.complex_value (); \ + ComplexMatrix result = op (m1, c2, ignore_nan); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + else \ + { \ + Matrix m1 = arg1.matrix_value (); \ + \ + if (! error_state) \ + { \ + double d2 = arg2.double_value (); \ + Matrix result = op (m1, d2, ignore_nan); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + } \ + else \ + { \ + if (arg1_is_complex || arg2_is_complex) \ + { \ + ComplexMatrix m1 = arg1.complex_matrix_value (); \ + \ + if (! error_state) \ + { \ + ComplexMatrix m2 = arg2.complex_matrix_value (); \ + \ + if (! error_state) \ + { \ + ComplexMatrix result = op (m1, m2, ignore_nan); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + } \ + else \ + { \ + Matrix m1 = arg1.matrix_value (); \ + \ + if (! error_state) \ + { \ + Matrix m2 = arg2.matrix_value (); \ + \ + if (! error_state) \ + { \ + Matrix result = op (m1, m2, ignore_nan); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + } \ + } \ + } \ + else \ + panic_impossible (); \ + \ + return retval; \ +} while (0) DEFUN_DLD (min, args, nargout, "-*- texinfo -*-\n\ at @ -287,7 +431,9 @@ returns the smallest element of at var{x} dot \n\ \n\ For complex arguments, the magnitude of the elements are used for\n\ -comparison.\n\ +comparison. NaNs are ignored if possible unless an optional argument\n\ +of 'prefer-nan' is supplied. The argument can also be 'ignore-nan'\n\ +to make the default behavior explicit.\n\ \n\ If called with two output arguments, also returns the index of the\n\ minimum value(s). Thus,\n\ at @ -298,215 +444,7 @@ at noindent\n\ returns at var{x} = 0 and @var{ix} = 3.") { - octave_value_list retval; - - int nargin = args.length (); - - if (nargin < 1 || nargin > 2 || nargout > 2) - { - print_usage ("min"); - return retval; - } - - octave_value arg1; - octave_value arg2; - - switch (nargin) - { - case 2: - arg2 = args(1); - // Fall through... - - case 1: - arg1 = args(0); - break; - - default: - panic_impossible (); - break; - } - - if (nargin == 1 && (nargout == 1 || nargout == 0)) - { - if (arg1.is_real_type ()) - { - Matrix m = arg1.matrix_value (); - - if (! error_state) - { - if (m.rows () == 1) - retval(0) = m.row_min (); - else - retval(0) = m.column_min (); - } - } - else if (arg1.is_complex_type ()) - { - ComplexMatrix m = arg1.complex_matrix_value (); - - if (! error_state) - { - if (m.rows () == 1) - retval(0) = m.row_min (); - else - retval(0) = m.column_min (); - } - } - else - gripe_wrong_type_arg ("min", arg1); - } - else if (nargin == 1 && nargout == 2) - { - Array index; - - if (arg1.is_real_type ()) - { - Matrix m = arg1.matrix_value (); - - if (! error_state) - { - retval.resize (2); - - if (m.rows () == 1) - retval(0) = m.row_min (index); - else - retval(0) = m.column_min (index); - } - } - else if (arg1.is_complex_type ()) - { - ComplexMatrix m = arg1.complex_matrix_value (); - - if (! error_state) - { - retval.resize (2); - - if (m.rows () == 1) - retval(0) = m.row_min (index); - else - retval(0) = m.column_min (index); - } - } - else - gripe_wrong_type_arg ("min", arg1); - - int len = index.length (); - - if (len > 0) - { - RowVector idx (len); - - for (int i = 0; i < len; i++) - { - int tmp = index.elem (i) + 1; - idx.elem (i) = (tmp <= 0) - ? octave_NaN : static_cast (tmp); - } - - retval(1) = idx; - } - } - else if (nargin == 2) - { - 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 (); - ComplexMatrix m2 = arg2.complex_matrix_value (); - if (! error_state) - { - ComplexMatrix result = min (c1, m2); - if (! error_state) - retval(0) = result; - } - } - else - { - double d1 = arg1.double_value (); - Matrix m2 = arg2.matrix_value (); - - if (! error_state) - { - Matrix result = min (d1, m2); - if (! error_state) - retval(0) = result; - } - } - } - else if (arg2_is_scalar) - { - if (arg1_is_complex || arg2_is_complex) - { - ComplexMatrix m1 = arg1.complex_matrix_value (); - - if (! error_state) - { - Complex c2 = arg2.complex_value (); - ComplexMatrix result = min (m1, c2); - if (! error_state) - retval(0) = result; - } - } - else - { - Matrix m1 = arg1.matrix_value (); - - if (! error_state) - { - double d2 = arg2.double_value (); - Matrix result = min (m1, d2); - if (! error_state) - retval(0) = result; - } - } - } - else - { - if (arg1_is_complex || arg2_is_complex) - { - ComplexMatrix m1 = arg1.complex_matrix_value (); - - if (! error_state) - { - ComplexMatrix m2 = arg2.complex_matrix_value (); - - if (! error_state) - { - ComplexMatrix result = min (m1, m2); - if (! error_state) - retval(0) = result; - } - } - } - else - { - Matrix m1 = arg1.matrix_value (); - - if (! error_state) - { - Matrix m2 = arg2.matrix_value (); - - if (! error_state) - { - Matrix result = min (m1, m2); - if (! error_state) - retval(0) = result; - } - } - } - } - } - else - panic_impossible (); - - return retval; + MINMAX_DISPATCH (min); } DEFUN_DLD (max, args, nargout, at @ -523,7 +461,9 @@ returns the largest element of at var{x} dot \n\ \n\ For complex arguments, the magnitude of the elements are used for\n\ -comparison. +comparison. NaNs are ignored if possible unless an optional argument\n\ +of 'prefer-nan' is supplied. The argument can also be 'ignore-nan'\n\ +to make the default behavior explicit.\n\ \n\ If called with two output arguments, also returns the index of the\n\ maximum value(s). Thus,\n\ at @ -534,215 +474,7 @@ at noindent\n\ returns at var{x} = 5 and @var{ix} = 3.") { - octave_value_list retval; - - int nargin = args.length (); - - if (nargin < 1 || nargin > 2 || nargout > 2) - { - print_usage ("max"); - return retval; - } - - octave_value arg1; - octave_value arg2; - - switch (nargin) - { - case 2: - arg2 = args(1); - // Fall through... - - case 1: - arg1 = args(0); - break; - - default: - panic_impossible (); - break; - } - - if (nargin == 1 && (nargout == 1 || nargout == 0)) - { - if (arg1.is_real_type ()) - { - Matrix m = arg1.matrix_value (); - - if (! error_state) - { - if (m.rows () == 1) - retval(0) = m.row_max (); - else - retval(0) = m.column_max (); - } - } - else if (arg1.is_complex_type ()) - { - ComplexMatrix m = arg1.complex_matrix_value (); - - if (! error_state) - { - if (m.rows () == 1) - retval(0) = m.row_max (); - else - retval(0) = m.column_max (); - } - } - else - gripe_wrong_type_arg ("max", arg1); - } - else if (nargin == 1 && nargout == 2) - { - Array index; - - if (arg1.is_real_type ()) - { - Matrix m = arg1.matrix_value (); - - if (! error_state) - { - retval.resize (2); - - if (m.rows () == 1) - retval(0) = m.row_max (index); - else - retval(0) = m.column_max (index); - } - } - else if (arg1.is_complex_type ()) - { - ComplexMatrix m = arg1.complex_matrix_value (); - - if (! error_state) - { - retval.resize (2); - - if (m.rows () == 1) - retval(0) = m.row_max (index); - else - retval(0) = m.column_max (index); - } - } - else - gripe_wrong_type_arg ("max", arg1); - - int len = index.length (); - - if (len > 0) - { - RowVector idx (len); - - for (int i = 0; i < len; i++) - { - int tmp = index.elem (i) + 1; - idx.elem (i) = (tmp <= 0) - ? octave_NaN : static_cast (tmp); - } - - retval(1) = idx; - } - } - else if (nargin == 2) - { - 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 (); - ComplexMatrix m2 = arg2.complex_matrix_value (); - if (! error_state) - { - ComplexMatrix result = max (c1, m2); - if (! error_state) - retval(0) = result; - } - } - else - { - double d1 = arg1.double_value (); - Matrix m2 = arg2.matrix_value (); - - if (! error_state) - { - Matrix result = max (d1, m2); - if (! error_state) - retval(0) = result; - } - } - } - else if (arg2_is_scalar) - { - if (arg1_is_complex || arg2_is_complex) - { - ComplexMatrix m1 = arg1.complex_matrix_value (); - - if (! error_state) - { - Complex c2 = arg2.complex_value (); - ComplexMatrix result = max (m1, c2); - if (! error_state) - retval(0) = result; - } - } - else - { - Matrix m1 = arg1.matrix_value (); - - if (! error_state) - { - double d2 = arg2.double_value (); - Matrix result = max (m1, d2); - if (! error_state) - retval(0) = result; - } - } - } - else - { - if (arg1_is_complex || arg2_is_complex) - { - ComplexMatrix m1 = arg1.complex_matrix_value (); - - if (! error_state) - { - ComplexMatrix m2 = arg2.complex_matrix_value (); - - if (! error_state) - { - ComplexMatrix result = max (m1, m2); - if (! error_state) - retval(0) = result; - } - } - } - else - { - Matrix m1 = arg1.matrix_value (); - - if (! error_state) - { - Matrix m2 = arg2.matrix_value (); - - if (! error_state) - { - Matrix result = max (m1, m2); - if (! error_state) - retval(0) = result; - } - } - } - } - } - else - panic_impossible (); - - return retval; + MINMAX_DISPATCH (max); } /*