# HG changeset patch # User Axel Mathéi # Date 1364309022 14400 # Node ID 7ce21619a4b94f3b40e0910c72a08be004a4260b # Parent 29e03b0e7e8ddb735705222b1762c6890a242cee min Matlab compatibility issue (bug #33530) * max.cc (do_minmax_red_op, do_minmax_bin_op): New specializations. (do_minmax_body): Handle char arrays. New tests. * chNDArray.h, chNDArray.cc (charNDArray::min, charNDArray::max): New functions. diff --git a/libinterp/corefcn/max.cc b/libinterp/corefcn/max.cc --- a/libinterp/corefcn/max.cc +++ b/libinterp/corefcn/max.cc @@ -74,6 +74,47 @@ return retval; } +// Matlab returns double arrays for min/max operations on character +// arrays, so we specialize here to get that behavior. Other possible +// solutions are to convert the argument to double here and call the +// code for double, but that could waste memory, or to have the +// underlying charNDArray::min/max functions return NDArray instead of +// charNDArray, but that is inconsistent with the way other min/max +// functions work. + +template <> +octave_value_list +do_minmax_red_op (const octave_value& arg, + int nargout, int dim, bool ismin) +{ + octave_value_list retval; + charNDArray array = octave_value_extract (arg); + + if (error_state) + return retval; + + if (nargout == 2) + { + retval.resize (2); + Array idx; + if (ismin) + retval(0) = NDArray (array.min (idx, dim)); + else + retval(0) = NDArray (array.max (idx, dim)); + + retval(1) = octave_value (idx, true, true); + } + else + { + if (ismin) + retval(0) = NDArray (array.min (dim)); + else + retval(0) = NDArray (array.max (dim)); + } + + return retval; +} + // Specialization for bool arrays. template <> octave_value_list @@ -154,6 +195,61 @@ return retval; } +// Matlab returns double arrays for min/max operations on character +// arrays, so we specialize here to get that behavior. Other possible +// solutions are to convert the arguments to double here and call the +// code for double, but that could waste a lot of memory, or to have the +// underlying charNDArray::min/max functions return NDArray instead of +// charNDArray, but that is inconsistent with the way other min/max +// functions work. + +template <> +octave_value +do_minmax_bin_op (const octave_value& argx, + const octave_value& argy, bool ismin) +{ + octave_value retval; + + if (argx.is_scalar_type () == 1) + { + char x = octave_value_extract (argx); + charNDArray y = octave_value_extract (argy); + + if (error_state) + ; + else if (ismin) + retval = NDArray (min (x, y)); + else + retval = NDArray (max (x, y)); + } + else if (argy.is_scalar_type () == 1) + { + charNDArray x = octave_value_extract (argx); + char y = octave_value_extract (argy); + + if (error_state) + ; + else if (ismin) + retval = NDArray (min (x, y)); + else + retval = NDArray (max (x, y)); + } + else + { + charNDArray x = octave_value_extract (argx); + charNDArray y = octave_value_extract (argy); + + if (error_state) + ; + else if (ismin) + retval = NDArray (min (x, y)); + else + retval = NDArray (max (x, y)); + } + + return retval; +} + static octave_value_list do_minmax_body (const octave_value_list& args, int nargout, bool ismin) @@ -227,6 +323,9 @@ case btyp_float_complex: retval = do_minmax_red_op (arg, nargout, dim, ismin); break; + case btyp_char: + retval = do_minmax_red_op (arg, nargout, dim, ismin); + break; #define MAKE_INT_BRANCH(X) \ case btyp_ ## X: \ retval = do_minmax_red_op (arg, nargout, dim, ismin); \ @@ -251,7 +350,11 @@ { 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); + builtin_type_t rtyp; + if (xtyp == btyp_char && ytyp == btyp_char) + rtyp = btyp_char; + else + rtyp = btyp_mixed_numeric (xtyp, ytyp); switch (rtyp) { @@ -281,6 +384,9 @@ case btyp_float_complex: retval = do_minmax_bin_op (argx, argy, ismin); break; + case btyp_char: + retval = do_minmax_bin_op (argx, argy, ismin); + break; #define MAKE_INT_BRANCH(X) \ case btyp_ ## X: \ retval = do_minmax_bin_op (argx, argy, ismin); \ @@ -361,6 +467,10 @@ %!assert (min ([1, 4, 2, 3]), 1) %!assert (min ([1; -10; 5; -2]), -10) %!assert (min ([4, i; -2, 2]), [-2, i]) +%!assert (min (char(42)), 42) +%!assert (min (char(21), char(3)), 3) +%!assert (min([char(21), char(3)]), 3) +%!assert (min([char(100) char(3)], [char(42) char(42)]), [42 3]) %!test %! x = reshape (1:8, [2,2,2]); diff --git a/liboctave/array/chNDArray.cc b/liboctave/array/chNDArray.cc --- a/liboctave/array/chNDArray.cc +++ b/liboctave/array/chNDArray.cc @@ -92,6 +92,30 @@ return *this; } +charNDArray +charNDArray::max (int dim) const +{ + return do_mx_minmax_op (*this, dim, mx_inline_max); +} + +charNDArray +charNDArray::max (Array& idx_arg, int dim) const +{ + return do_mx_minmax_op (*this, idx_arg, dim, mx_inline_max); +} + +charNDArray +charNDArray::min (int dim) const +{ + return do_mx_minmax_op (*this, dim, mx_inline_min); +} + +charNDArray +charNDArray::min (Array& idx_arg, int dim) const +{ + return do_mx_minmax_op (*this, idx_arg, dim, mx_inline_min); +} + charNDArray& charNDArray::insert (const charNDArray& a, octave_idx_type r, octave_idx_type c) { @@ -139,6 +163,48 @@ return Array::diag (m, n); } +charNDArray +min (char d, const charNDArray& m) +{ + return do_sm_binary_op + (d, m, mx_inline_xmin); +} + +charNDArray +min (const charNDArray& m, char d) +{ + return do_ms_binary_op + (m, d, mx_inline_xmin); +} + +charNDArray +min (const charNDArray& a, const charNDArray& b) +{ + return do_mm_binary_op + (a, b, mx_inline_xmin, mx_inline_xmin, mx_inline_xmin, "min"); +} + +charNDArray +max (char d, const charNDArray& m) +{ + return do_sm_binary_op + (d, m, mx_inline_xmax); +} + +charNDArray +max (const charNDArray& m, char d) +{ + return do_ms_binary_op + (m, d, mx_inline_xmax); +} + +charNDArray +max (const charNDArray& a, const charNDArray& b) +{ + return do_mm_binary_op + (a, b, mx_inline_xmax, mx_inline_xmax, mx_inline_xmax, "max"); +} + NDS_CMP_OPS (charNDArray, char) NDS_BOOL_OPS (charNDArray, char) diff --git a/liboctave/array/chNDArray.h b/liboctave/array/chNDArray.h --- a/liboctave/array/chNDArray.h +++ b/liboctave/array/chNDArray.h @@ -73,6 +73,11 @@ charNDArray concat (const charNDArray& rb, const Array& ra_idx); charNDArray concat (const NDArray& rb, const Array& ra_idx); + charNDArray max (int dim = -1) const; + charNDArray max (Array& index, int dim = -1) const; + charNDArray min (int dim = -1) const; + charNDArray min (Array& index, int dim = -1) const; + charNDArray& insert (const charNDArray& a, octave_idx_type r, octave_idx_type c); charNDArray& insert (const charNDArray& a, const Array& ra_idx); @@ -97,6 +102,13 @@ charNDArray diag (octave_idx_type m, octave_idx_type n) const; }; +extern OCTAVE_API charNDArray min (char d, const charNDArray& m); +extern OCTAVE_API charNDArray min (const charNDArray& m, char d); +extern OCTAVE_API charNDArray min (const charNDArray& a, const charNDArray& b); +extern OCTAVE_API charNDArray max (char d, const charNDArray& m); +extern OCTAVE_API charNDArray max (const charNDArray& m, char d); +extern OCTAVE_API charNDArray max (const charNDArray& a, const charNDArray& b); + NDS_CMP_OP_DECLS (charNDArray, char, OCTAVE_API) NDS_BOOL_OP_DECLS (charNDArray, char, OCTAVE_API)