Mercurial > hg > octave-nkf
changeset 5205:59592dcbb5d8
[project @ 2005-03-15 16:04:56 by jwe]
author | jwe |
---|---|
date | Tue, 15 Mar 2005 16:04:57 +0000 |
parents | 2a44a667da02 |
children | 61bf9cfc38da |
files | scripts/ChangeLog scripts/set/ismember.m scripts/set/unique.m src/ChangeLog src/DLD-FUNCTIONS/cellfun.cc src/Makefile.in |
diffstat | 6 files changed, 309 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,3 +1,7 @@ +2005-03-15 David Bateman <dbateman@free.fr> + + * set/unique.m, set/ismember.m: Handle cell arrays. + 2005-03-09 John W. Eaton <jwe@octave.org> * statistics/Makefile.in (bin-dist): Delete target.
--- a/scripts/set/ismember.m +++ b/scripts/set/ismember.m @@ -37,12 +37,33 @@ if (isempty (a) || isempty (S)) c = zeros (ra, ca); else + if (iscell (a) && ! iscell (S)) + tmp{1} = S; + S = tmp; + endif + if (! iscell (a) && iscell (S)) + tmp{1} = a; + a = tmp; + endif S = unique (S(:)); lt = length (S); if (lt == 1) - c = (a == S); - elseif (ra*ca == 1) - c = any (a == S); + if (iscell (a) || iscell (S)) + c = cellfun ("length", a) == cellfun ("length", S); + idx = find (c); + c(idx) = all (char (a(idx)) == repmat (char (S), length (idx), 1), 2); + else + c = (a == S); + endif + elseif (prod (size (a)) == 1) + if (iscell (a) || iscell (S)) + c = cellfun ("length", a) == cellfun ("length", S); + idx = find (c); + c(idx) = all (repmat (char (a), length (idx), 1) == char (S(idx)), 2); + c = any(c); + else + c = any (a == S); + endif else ## Magic: the following code determines for each a, the index i ## such that S(i)<= a < S(i+1). It does this by sorting the a @@ -76,7 +97,14 @@ [v, p] = sort ([S(2:lt); a(:)]); idx(p) = cumsum (p <= lt-1) + 1; idx = idx(lt:lt+ra*ca-1); - c = (a == reshape (S(idx), size (a))); + if (iscell (a) || iscell (S)) + c = (cellfun ("length", a) + == reshape (cellfun ("length", S(idx)), size (a))); + idx2 = find (c); + c(idx2) = all (char (a(idx2)) == char (S(idx)(idx2)), 2); + else + c = (a == reshape (S (idx), size (a))); + endif endif endif
--- a/scripts/set/unique.m +++ b/scripts/set/unique.m @@ -60,7 +60,14 @@ if (nargin == 2) [y, i] = sortrows (y); - match = all ((y(1:n-1,:) == y(2:n,:))'); + if (iscell (y)) + match = cellfun ("size", y(1:n-1,:), 1) == cellfun ("size", y(2:n,:), 1); + idx = find (match); + match(idx) = all (char (y(idx)) == char (y(idx+1)), 2); + match = all (match'); + else + match = all ([y(1:n-1,:) == y(2:n,:)]'); + endif idx = find (match); y(idx,:) = []; else @@ -68,7 +75,13 @@ y = y(:); endif [y, i] = sort (y); - match = y(1:n-1) == y(2:n); + if (iscell (y)) + match = cellfun ("length", y(1:n-1)) == cellfun ("length", y(2:n)); + idx = find(match); + match(idx) = all (char (y(idx)) == char (y(idx+1)), 2); + else + match = [y(1:n-1) == y(2:n)]; + endif idx = find (match); y(idx) = []; endif @@ -94,3 +107,5 @@ %!assert(unique([1 2]),[1 2]) %!assert(unique([1;2]),[1;2]) %!assert(unique([1,NaN,Inf,NaN,Inf]),[1,Inf,NaN,NaN]) +%!assert(unique({'Foo','Bar','Foo'}),{'Bar','Foo'}) +%!assert(unique({'Foo','Bar','FooBar'}),{'Bar','Foo','FooBar'})
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2005-03-15 John W. Eaton <jwe@octave.org> + + * cellfun.cc: New function from Octave-forge. Adapt to Octave + coding standards. + * Makefile.in (DLD_XSRC): Add it to the list. + 2005-03-14 John W. Eaton <jwe@octave.org> * DLD-FUNCTIONS/dispatch.cc (Fbuiltin): Avoid crash if symbol
new file mode 100644 --- /dev/null +++ b/src/DLD-FUNCTIONS/cellfun.cc @@ -0,0 +1,249 @@ +/* + +Copyright (C) 2005 Mohamed Kamoun + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string> + +#include "lo-mappers.h" + +#include "Cell.h" +#include "defun-dld.h" +#include "parse.h" +#include "variables.h" + +DEFUN_DLD (cellfun, args, , + " -*- texinfo -*-\n\ +@deftypefn {Lodable Function} {} cellfun (@var{name}, @var{c})\n\ +@deftypefnx {Lodable Function} {} cellfun (\"isclass\", @var{c}, @var{class})\n\ +@deftypefnx {Lodable Function} {} cellfun (\"size\", @var{c}, @var{k})\n\ +@deftypefnx {Lodable Function} {} cellfun (@var{func}, @var{c})\n\ +\n\ +Evaluate the function named @var{name} on the elements of the cell array\n\ +@var{c}. Elements in cell_array are passed on to the named function\n\ +individually. The function @var{name} can be one of the functions\n\ +\n\ +@table @code\n\ +@item isempty\n\ +Return 1 when for non empty elements and 0 for others.\n\ +@item islogical\n\ +Return 1 for logical elements.\n\ +@item isreal\n\ +Return 1 for real elements.\n\ +@item length\n\ +Return a vector of the lengths of cell elements.\n\ +@item dims\n\ +Return the number of dimensions of each element.\n\ +@item prodofsize\n\ +Return the product of dimensions of each element.\n\ +@item size\n\ +Return the size along the @var{k}-th dimension.\n\ +@item isclass\n\ +Return 1 for elements of @var{class}.\n\ +@end table\n\ +\n\ +Additionally, @code{cellfun} accepts an arbitrary function @var{func}\n\ +in the form of an inline function, function handle, or the name of a\n\ +function (in a character string). The function should take a single\n\ +argument and return a single value, and in the case of a character string\n\ +argument, the argument must be named @var{x}. For example\n\ +\n\ +@example\n\ +@group\n\ +cellfun (\"tolower(x)\", @{\"Foo\", \"Bar\", \"FooBar\"@})\n\ +@result{} ans = @{\"foo\", \"bar\", \"foobar\"@}\n\ +@end group\n\ +@end example\n\ +\n\ +@end deftypefn") +{ + octave_value retval; + + std::string name = "function"; + + octave_function *func = 0; + + int nargin = args.length (); + + if (nargin < 2) + { + error ("cellfun: you must supply at least 2 arguments"); + print_usage ("cellfun"); + return retval; + } + + if (args(0).is_function_handle () || args(0).is_inline_function ()) + { + func = args(0).function_value (); + + if (error_state) + return retval; + } + else if (args(0).is_string ()) + name = args(0).string_value (); + else + { + error ("cellfun: first argument must be a string"); + return retval; + } + + if (! args(1).is_cell ()) + { + error ("cellfun: second argument must be a cell"); + + return retval; + } + + Cell f_args = args(1).cell_value (); + + int k = f_args.numel (); + + if (name == "isempty") + { + boolNDArray result (f_args.dims ()); + for (int count = 0; count < k ; count++) + result(count) = f_args.elem(count).is_empty(); + retval = result; + } + else if (name == "islogical") + { + boolNDArray result (f_args.dims ()); + for (int count= 0; count < k ; count++) + result(count) = f_args.elem(count).is_bool_type (); + retval = result; + } + else if (name == "isreal") + { + boolNDArray result (f_args.dims ()); + for (int count= 0; count < k ; count++) + result(count) = f_args.elem(count).is_real_type (); + retval = result; + } + else if (name == "length") + { + NDArray result (f_args.dims ()); + for (int count= 0; count < k ; count++) + result(count) = double (f_args.elem(count).numel ()); + retval = result; + } + else if (name == "ndims") + { + NDArray result (f_args.dims ()); + for (int count = 0; count < k ; count++) + result(count) = double ((f_args.elem(count).dims ()).numel ()); + retval = result; + } + else if (name == "prodofsize") + { + NDArray result (f_args.dims ()); + for (int count = 0; count < k ; count++) + result(count) = double ((f_args.elem(count).dims ()).numel ()); + retval = result; + } + else if (name == "size") + { + if (nargin == 3) + { + int d = args(2).nint_value () - 1; + + if (d < 0) + error ("cellfun: third argument must be a postive integer"); + + if (!error_state) + { + NDArray result (f_args.dims ()); + for (int count = 0; count < k ; count++) + { + dim_vector dv = f_args.elem(count).dims (); + if (d < dv.length ()) + result(count) = double (dv(d)); + else + result(count) = 1.0; + } + retval = result; + } + } + else + error ("Not enough argument for size"); + } + else if (name == "isclass") + { + if (nargin == 3) + { + std::string class_name = args(2).string_value(); + boolNDArray result (f_args.dims ()); + for (int count = 0; count < k ; count++) + result(count) = (f_args.elem(count).class_name() == class_name); + + retval = result; + } + else + error ("Not enough argument for isclass"); + } + else + { + std::string fcn_name; + + if (! func) + { + fcn_name = unique_symbol_name ("__cellfun_fcn_"); + std::string fname = "function y = "; + fname.append (fcn_name); + fname.append ("(x) y = "); + func = extract_function (args(0), "cellfun", fcn_name, fname, + "; endfunction"); + } + + if (! func) + error ("unknown function"); + else + { + Cell result (f_args.dims ()); + + for (int count = 0; count < k ; count++) + { + octave_value_list tmp + = func->do_multi_index_op (1, f_args.elem (count)); + result(count) = tmp(0); + + if (error_state) + break; + } + + if (! error_state) + retval = result; + + if (! fcn_name.empty ()) + clear_function (fcn_name); + } + } + + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
--- a/src/Makefile.in +++ b/src/Makefile.in @@ -42,7 +42,7 @@ OPT_HANDLERS := DASPK-opts.cc DASRT-opts.cc DASSL-opts.cc \ LSODE-opts.cc NLEqn-opts.cc Quad-opts.cc -DLD_XSRC := balance.cc besselj.cc betainc.cc chol.cc colamd.cc \ +DLD_XSRC := balance.cc besselj.cc betainc.cc cellfun.cc chol.cc colamd.cc \ colloc.cc daspk.cc dasrt.cc dassl.cc det.cc dispatch.cc \ eig.cc expm.cc fft.cc fft2.cc fftn.cc fftw_wisdom.cc \ filter.cc find.cc fsolve.cc gammainc.cc gcd.cc getgrent.cc \