octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: goals for 3.1


From: David Bateman
Subject: Re: goals for 3.1
Date: Mon, 18 Feb 2008 18:10:08 +0100
User-agent: Thunderbird 2.0.0.6 (X11/20070914)

John W. Eaton wrote:
>    9. Mapper functions like real, imag, and mod should preserve type
>       (are there others?)
>   
Most of the mapper functions take a single argument, except mod, rem and
atan2. So these were addressed by my recent mapper patch. As for these
three functions, mod/rem must be made to accept integer arguments and
atan2 should fail for integer arguments. Checking matlabR2007b it seems
that the compatiable behavior is a bit odd, as mod(uint8(5),4),
mod(uint8(1:5),4) and mod(5, uint8(4)) are acceptable, but mod(1:5,
uint8(4)) isn't. I tried to duplicate this behavior though it doesn't
seem too logical.

Equally rem and mod for 64-bit integer arguments do not seem to be
defined, as some of the arithmetic operators are not defined for the 64
bit types... This is easy to duplicate as the same behavior exists in
Octave.

Please find attached a patch that address these three two argument
mapper functions.

Regards
David


-- 
David Bateman                                address@hidden
Motorola Labs - Paris                        +33 1 69 35 48 04 (Ph) 
Parc Les Algorithmes, Commune de St Aubin    +33 6 72 01 06 33 (Mob) 
91193 Gif-Sur-Yvette FRANCE                  +33 1 69 35 77 01 (Fax) 

The information contained in this communication has been classified as: 

[x] General Business Information 
[ ] Motorola Internal Use Only 
[ ] Motorola Confidential Proprietary

# HG changeset patch
# User David Bateman <address@hidden>
# Date 1203354509 -3600
# Node ID b0b322dbae6c8af9745f474717b116226a17a48f
# Parent  68bfb8aea1b3f9ce0a3ac73a5e7739d6b93e7bb0
Treat integer types for mod/rem correctly

diff -r 68bfb8aea1b3 -r b0b322dbae6c scripts/ChangeLog
--- a/scripts/ChangeLog Sun Feb 17 23:27:55 2008 +0100
+++ b/scripts/ChangeLog Mon Feb 18 18:08:29 2008 +0100
@@ -1,3 +1,7 @@ 2008-02-15  Timo Lindfors  <timo.lindfor
+2008-02-18  David Bateman  <address@hidden>
+
+       * general/rem.m, general/mod.m: Treat integer types correctly.
+
 2008-02-15  Timo Lindfors  <address@hidden>
 
        * statistics/tests/kruskal_wallis_test.m: Handle ties.
diff -r 68bfb8aea1b3 -r b0b322dbae6c scripts/general/mod.m
--- a/scripts/general/mod.m     Sun Feb 17 23:27:55 2008 +0100
+++ b/scripts/general/mod.m     Mon Feb 18 18:08:29 2008 +0100
@@ -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 @@ function r = mod (x, y)
     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 @@ endfunction
 %!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)))
diff -r 68bfb8aea1b3 -r b0b322dbae6c scripts/general/rem.m
--- a/scripts/general/rem.m     Sun Feb 17 23:27:55 2008 +0100
+++ b/scripts/general/rem.m     Mon Feb 18 18:08:29 2008 +0100
@@ -43,21 +43,26 @@ function r = rem (x, y)
     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 @@ endfunction
 
 %!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]));
diff -r 68bfb8aea1b3 -r b0b322dbae6c src/ChangeLog
--- a/src/ChangeLog     Sun Feb 17 23:27:55 2008 +0100
+++ b/src/ChangeLog     Mon Feb 18 18:08:29 2008 +0100
@@ -1,3 +1,7 @@ 2008-02-16  David Bateman  <address@hidden
+2008-02-18  David Bateman  <address@hidden>
+
+       * data.cc (Fatan2): Reject arguments that are integer types.
+
 2008-02-16  David Bateman  <address@hidden>
 
        * Makefile.in (OV_SRC): Remove ov-mapper.cc.
diff -r 68bfb8aea1b3 -r b0b322dbae6c src/data.cc
--- a/src/data.cc       Sun Feb 17 23:27:55 2008 +0100
+++ b/src/data.cc       Mon Feb 18 18:08:29 2008 +0100
@@ -202,76 +202,81 @@ and @var{x}.  The result is in range -pi
 
   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)
+               {
+                 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)
+               {
+                 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)
+               {
+                 Matrix x = arg_x.matrix_value ();
+
+                 if (! error_state)
+                   retval = map_m_m (atan2, y, x);
+               }
+           }
+         else
+           error ("atan2: nonconformant matrices");
        }
-      else if (y_is_scalar)
-       {
-         double y = arg_y.double_value ();
-
-         if (! error_state)
-           {
-             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)
-           {
-             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)
-           {
-             Matrix x = arg_x.matrix_value ();
-
-             if (! error_state)
-               retval = map_m_m (atan2, y, x);
-           }
-       }
-      else
-       error ("atan2: nonconformant matrices");
     }
   else
     print_usage ();

reply via email to

[Prev in Thread] Current Thread [Next in Thread]