Mercurial > hg > octave-nkf
changeset 16370:7ce21619a4b9
min Matlab compatibility issue (bug #33530)
* max.cc (do_minmax_red_op<charNDArray>,
do_minmax_bin_op<charNDArray>): New specializations.
(do_minmax_body): Handle char arrays. New tests.
* chNDArray.h, chNDArray.cc (charNDArray::min, charNDArray::max):
New functions.
author | Axel Mathéi <axel.mathei@gmail.com> |
---|---|
date | Tue, 26 Mar 2013 10:43:42 -0400 |
parents | 29e03b0e7e8d |
children | effe80808118 |
files | libinterp/corefcn/max.cc liboctave/array/chNDArray.cc liboctave/array/chNDArray.h |
diffstat | 3 files changed, 189 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- 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<charNDArray> (const octave_value& arg, + int nargout, int dim, bool ismin) +{ + octave_value_list retval; + charNDArray array = octave_value_extract<charNDArray> (arg); + + if (error_state) + return retval; + + if (nargout == 2) + { + retval.resize (2); + Array<octave_idx_type> 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<charNDArray> (const octave_value& argx, + const octave_value& argy, bool ismin) +{ + octave_value retval; + + if (argx.is_scalar_type () == 1) + { + char x = octave_value_extract<char> (argx); + charNDArray y = octave_value_extract<charNDArray> (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<charNDArray> (argx); + char y = octave_value_extract<char> (argy); + + if (error_state) + ; + else if (ismin) + retval = NDArray (min (x, y)); + else + retval = NDArray (max (x, y)); + } + else + { + charNDArray x = octave_value_extract<charNDArray> (argx); + charNDArray y = octave_value_extract<charNDArray> (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<FloatComplexNDArray> (arg, nargout, dim, ismin); break; + case btyp_char: + retval = do_minmax_red_op<charNDArray> (arg, nargout, dim, ismin); + break; #define MAKE_INT_BRANCH(X) \ case btyp_ ## X: \ retval = do_minmax_red_op<X ## NDArray> (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<FloatComplexNDArray> (argx, argy, ismin); break; + case btyp_char: + retval = do_minmax_bin_op<charNDArray> (argx, argy, ismin); + break; #define MAKE_INT_BRANCH(X) \ case btyp_ ## X: \ retval = do_minmax_bin_op<X ## NDArray> (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]);
--- 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<char> (*this, dim, mx_inline_max); +} + +charNDArray +charNDArray::max (Array<octave_idx_type>& idx_arg, int dim) const +{ + return do_mx_minmax_op<char> (*this, idx_arg, dim, mx_inline_max); +} + +charNDArray +charNDArray::min (int dim) const +{ + return do_mx_minmax_op<char> (*this, dim, mx_inline_min); +} + +charNDArray +charNDArray::min (Array<octave_idx_type>& idx_arg, int dim) const +{ + return do_mx_minmax_op<char> (*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<char>::diag (m, n); } +charNDArray +min (char d, const charNDArray& m) +{ + return do_sm_binary_op<charNDArray::element_type, char, charNDArray::element_type> + (d, m, mx_inline_xmin); +} + +charNDArray +min (const charNDArray& m, char d) +{ + return do_ms_binary_op<charNDArray::element_type, charNDArray::element_type, char> + (m, d, mx_inline_xmin); +} + +charNDArray +min (const charNDArray& a, const charNDArray& b) +{ + return do_mm_binary_op<charNDArray::element_type, charNDArray::element_type, charNDArray::element_type> + (a, b, mx_inline_xmin, mx_inline_xmin, mx_inline_xmin, "min"); +} + +charNDArray +max (char d, const charNDArray& m) +{ + return do_sm_binary_op<charNDArray::element_type, char, charNDArray::element_type> + (d, m, mx_inline_xmax); +} + +charNDArray +max (const charNDArray& m, char d) +{ + return do_ms_binary_op<charNDArray::element_type, charNDArray::element_type, char> + (m, d, mx_inline_xmax); +} + +charNDArray +max (const charNDArray& a, const charNDArray& b) +{ + return do_mm_binary_op<charNDArray::element_type, charNDArray::element_type, charNDArray::element_type> + (a, b, mx_inline_xmax, mx_inline_xmax, mx_inline_xmax, "max"); +} + NDS_CMP_OPS (charNDArray, char) NDS_BOOL_OPS (charNDArray, char)
--- a/liboctave/array/chNDArray.h +++ b/liboctave/array/chNDArray.h @@ -73,6 +73,11 @@ charNDArray concat (const charNDArray& rb, const Array<octave_idx_type>& ra_idx); charNDArray concat (const NDArray& rb, const Array<octave_idx_type>& ra_idx); + charNDArray max (int dim = -1) const; + charNDArray max (Array<octave_idx_type>& index, int dim = -1) const; + charNDArray min (int dim = -1) const; + charNDArray min (Array<octave_idx_type>& 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<octave_idx_type>& 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)