Mercurial > hg > octave-lyh
changeset 7494:bd2bd04e68ca
Treat integer types for mod/rem correctly
author | David Bateman <dbateman@free.fr> |
---|---|
date | Mon, 18 Feb 2008 18:08:29 +0100 |
parents | f1bce8450fd0 |
children | 507132cef358 |
files | scripts/ChangeLog scripts/general/mod.m scripts/general/rem.m src/data.cc |
diffstat | 4 files changed, 116 insertions(+), 68 deletions(-) [+] |
line wrap: on
line diff
--- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -3,6 +3,10 @@ * time/datestr.m: Avoid confusion for datenum vectors that are 6 elements wide. +2008-02-18 David Bateman <dbateman@free.fr> + + * general/rem.m, general/mod.m: Treat integer types correctly. + 2008-02-15 Timo Lindfors <timo.lindfors@iki.fi> * statistics/tests/kruskal_wallis_test.m: Handle ties.
--- a/scripts/general/mod.m +++ b/scripts/general/mod.m @@ -18,14 +18,15 @@ ## -*- texinfo -*- ## @deftypefn {Mapping Function} {} mod (@var{x}, @var{y}) -## Compute modulo function, using +## Compute modulo function. Conceptually this is given by ## ## @example ## x - y .* floor (x ./ y) ## @end example ## -## Note that this handles negative numbers correctly: -## @code{mod (-1, 3)} is 2, not -1 as @code{rem (-1, 3)} returns. +## and is written in a manner that the correct modulus is returned for +##integer types. This function handles negative values correctly. That +##is @code{mod (-1, 3)} is 2, not -1 as @code{rem (-1, 3)} returns. ## Also, @code{mod (@var{x}, 0)} returns @var{x}. ## ## An error message is printed if the dimensions of the arguments do not @@ -47,27 +48,42 @@ error ("mod: argument sizes must agree"); endif - ## Matlab allows complex arguments, but as far as I can tell, that's a - ## bunch of hooey. - if (isreal (x) && isreal (y)) nz = y != 0.0; if (all (nz(:))) ## No elements of y are zero. - r = x - y .* floor (x ./ y); + if (isinteger(x) || isinteger(y)) + if (isinteger (x)) + typ = class (x); + else + typ = class (y); + endif + r = x - y .* cast (floor (double(x) ./ double(y)), typ); + else + r = x - y .* floor (x ./ y); + endif elseif (isscalar (y)) ## y must be zero. r = x; else ## Some elements of y are zero. if (isscalar (x)) - r = x * ones (size (y)); + r = x * ones (size(y), class(y)); else r = x; x = x(nz); endif y = y(nz); - r(nz) = x - y .* floor (x ./ y); + if (isinteger(x) || isinteger(y)) + if (isinteger (x)) + typ = class (x); + else + typ = class (y); + endif + r(nz) = x - y .* floor (double(x) ./ double(y)); + else + r(nz) = x - y .* floor (x ./ y); + endif endif else error ("mod: complex arguments are not allowed"); @@ -101,3 +117,14 @@ %!assert (mod(-5,[3,0; 3,1]), [1, -5; 1, 0]); %!assert (mod(-5,[3,2; 3,1]), [1, 1; 1, 0]); +## integer types +%!assert (mod(uint8(5),uint8(4)),uint8(1)) +%!assert (mod(uint8([1:5]),uint8(4)),uint8([1,2,3,0,1])) +%!assert (mod(uint8([1:5]),uint8(0)),uint8([1:5])) +%!error (mod(uint8(5),int8(4))) + +## mixed integer/real types +%!assert (mod(uint8(5),4),uint8(1)) +%!assert (mod(5,uint8(4)),uint8(1)) +%!assert (mod(uint8([1:5]),4),uint8([1,2,3,0,1])) +%!error (mod([1:5],uint8(4)))
--- a/scripts/general/rem.m +++ b/scripts/general/rem.m @@ -43,21 +43,26 @@ error ("rem: argument sizes must agree"); endif - ## Matlab allows complex arguments, but as far as I can tell, that's a - ## bunch of hooey. - if (isreal (x) && isreal (y)) - r = x - y .* fix (x ./ y); + if (isinteger(x) || isinteger(y)) + if (isinteger (x)) + typ = class (x); + else + typ = class (y); + endif + r = x - y .* cast (fix (double (x) ./ double (y)), typ); + else + r = x - y .* fix (x ./ y); + endif else error ("rem: complex arguments are not allowed"); endif endfunction -%!assert(all (all (rem ([1, 2, 3; -1, -2, -3], 2) == [1, 0, 1; -1, 0, -1]))); +%!assert(rem ([1, 2, 3; -1, -2, -3], 2), [1, 0, 1; -1, 0, -1]); -%!assert(all (all (rem ([1, 2, 3; -1, -2, -3], 2 * ones (2, 3)) -%! == [1, 0, 1; -1, 0, -1]))); +%!assert(rem ([1, 2, 3; -1, -2, -3], 2 * ones (2, 3)),[1, 0, 1; -1, 0, -1]); %!error rem (); @@ -67,3 +72,10 @@ %!error rem (i, 1); +%!assert(rem (uint8([1, 2, 3; -1, -2, -3]), uint8 (2)), uint8([1, 0, 1; -1, 0, -1])); + +%!assert(uint8(rem ([1, 2, 3; -1, -2, -3], 2 * ones (2, 3))),uint8([1, 0, 1; -1, 0, -1])); + +%!error rem (uint(8),int8(5)); + +%!error rem (uint8([1, 2]), uint8([3, 4, 5]));
--- a/src/data.cc +++ b/src/data.cc @@ -202,76 +202,81 @@ if (nargin == 2 && args(0).is_defined () && args(1).is_defined ()) { - octave_value arg_y = args(0); - octave_value arg_x = args(1); - - octave_idx_type y_nr = arg_y.rows (); - octave_idx_type y_nc = arg_y.columns (); - - octave_idx_type x_nr = arg_x.rows (); - octave_idx_type x_nc = arg_x.columns (); - - int arg_y_empty = empty_arg ("atan2", y_nr, y_nc); - int arg_x_empty = empty_arg ("atan2", x_nr, x_nc); - - if (arg_y_empty > 0 && arg_x_empty > 0) - return octave_value (Matrix ()); - else if (arg_y_empty || arg_x_empty) - return retval; - - octave_idx_type y_is_scalar = (y_nr == 1 && y_nc == 1); - octave_idx_type x_is_scalar = (x_nr == 1 && x_nc == 1); - - if (y_is_scalar && x_is_scalar) + if (args(0).is_integer_type () || args(0).is_integer_type ()) + error ("atan2: not defined for integer types"); + else { - double y = arg_y.double_value (); - - if (! error_state) + octave_value arg_y = args(0); + octave_value arg_x = args(1); + + octave_idx_type y_nr = arg_y.rows (); + octave_idx_type y_nc = arg_y.columns (); + + octave_idx_type x_nr = arg_x.rows (); + octave_idx_type x_nc = arg_x.columns (); + + int arg_y_empty = empty_arg ("atan2", y_nr, y_nc); + int arg_x_empty = empty_arg ("atan2", x_nr, x_nc); + + if (arg_y_empty > 0 && arg_x_empty > 0) + return octave_value (Matrix ()); + else if (arg_y_empty || arg_x_empty) + return retval; + + octave_idx_type y_is_scalar = (y_nr == 1 && y_nc == 1); + octave_idx_type x_is_scalar = (x_nr == 1 && x_nc == 1); + + if (y_is_scalar && x_is_scalar) { - double x = arg_x.double_value (); + double y = arg_y.double_value (); if (! error_state) - retval = atan2 (y, x); + { + double x = arg_x.double_value (); + + if (! error_state) + retval = atan2 (y, x); + } } - } - else if (y_is_scalar) - { - double y = arg_y.double_value (); - - if (! error_state) + else if (y_is_scalar) { - Matrix x = arg_x.matrix_value (); + double y = arg_y.double_value (); if (! error_state) - retval = map_d_m (atan2, y, x); + { + Matrix x = arg_x.matrix_value (); + + if (! error_state) + retval = map_d_m (atan2, y, x); + } } - } - else if (x_is_scalar) - { - Matrix y = arg_y.matrix_value (); - - if (! error_state) + else if (x_is_scalar) { - double x = arg_x.double_value (); + Matrix y = arg_y.matrix_value (); if (! error_state) - retval = map_m_d (atan2, y, x); + { + double x = arg_x.double_value (); + + if (! error_state) + retval = map_m_d (atan2, y, x); + } } - } - else if (y_nr == x_nr && y_nc == x_nc) - { - Matrix y = arg_y.matrix_value (); - - if (! error_state) + else if (y_nr == x_nr && y_nc == x_nc) { - Matrix x = arg_x.matrix_value (); + Matrix y = arg_y.matrix_value (); if (! error_state) - retval = map_m_m (atan2, y, x); + { + Matrix x = arg_x.matrix_value (); + + if (! error_state) + retval = map_m_m (atan2, y, x); + } } + else + error ("atan2: nonconformant matrices"); } - else - error ("atan2: nonconformant matrices"); } else print_usage ();