octave-maintainers
[Top][All Lists]
Advanced

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

Speed up 'unique'


From: Daniel J Sebald
Subject: Speed up 'unique'
Date: Wed, 17 Dec 2008 04:52:43 -0600
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041020

Attached is a patch that tweaks unique.m to cut the time of the
following test by 4:

function testfunc3(m, varargin)
 x = [[1:20] [20:-1:1]];
 tstart = cputime();
 for i=1:5000
   [y i j] = unique(x);
 end
 cputime() - tstart
end

The reason for the improvement is that all the testing for the options
is avoided if no options are present.  (I.e., avoids three calls to
'strmatch' and a couple conditionals.)  Also, 'prepad' really isn't a
necessary call, as I see it.

If one looks closely at the handling of options, I added a recursive
call to make sure the options are unique.  Otherwise, something like
this fails:

unique([1:10], 'first', 'first')

The recursion looks funny, but because of the added check on the number
of arguments, it is not an indefinite loop.

Dan
--- unique.m.orig       2008-12-17 03:08:02.000000000 -0600
+++ unique.m    2008-12-17 04:45:08.590020461 -0600
@@ -45,26 +45,31 @@
     print_usage ();
   endif
 
-  ## parse options
-  if (iscellstr (varargin))
-    optfirst = strmatch ('first', varargin) > 0;
-    optlast = strmatch ('last', varargin) > 0;
-    optrows = strmatch ('rows', varargin) > 0 && size (x, 2) > 1;
-    if (optfirst && optlast)
-      error ("unique: cannot specify both 'last' and 'first'.");
-    elseif (optfirst + optlast + optrows != nargin-1)
-      error ("unique: invalid option.");
+  if (nargin > 1)
+
+    ## parse options
+    if (iscellstr (varargin))
+      varargin = unique(varargin);
+      optfirst = strmatch ('first', varargin) > 0;
+      optlast = strmatch ('last', varargin) > 0;
+      optrows = strmatch ('rows', varargin) > 0 && size (x, 2) > 1;
+      if (optfirst && optlast)
+        error ("unique: cannot specify both 'last' and 'first'.");
+      elseif (optfirst + optlast + optrows != nargin-1)
+        error ("unique: invalid option.");
+      endif
+    else
+      error ("unique: options must be strings");
     endif
-    optlast = ! optfirst;
-  else
-    error ("unique: options must be strings");
-  endif
 
-  if (iscell (x))
-    if (optrows)
+    if (optrows && iscell (x))
       warning ("unique: 'rows' is ignored for cell arrays");
       optrows = false;
     endif
+
+  else
+    optfirst = 0;
+    optrows = 0;
   endif
 
   if (optrows)
@@ -101,12 +106,11 @@
     y(idx) = [];
   endif
 
-  ## I don't know why anyone would need reverse indices, but it
-  ## was an interesting challenge.  I welcome cleaner solutions.
   if (nargout >= 3)
     j = i;
-    j(i) = cumsum (prepad (! match, n, 1));
+    j(i) = cumsum ([1 !match]);
   endif
+
   if (optfirst)
     i(idx+1) = [];
   else

reply via email to

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