Re: outer product implementation
David Bateman <[email protected]> Sun, 24 Sep 2006 21:53:26 +0200
| Newsgroups | gmane.comp.gnu.octave.sources |
|---|---|
| Organization | Motorola CRM |
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format. --------------080706000203030102000206 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Muthiah Annamalai wrote: > David, > Thanks for the tip on inline functions & the code. > Im still not sure if what I did was inline functions, but > the code works correctly after I have integrated the code > you posted earlier. > > Im attaching the 3rd attempt to outer product implementation. > > It can take 2 forms of functions AFAIK: ones by @ sign, > and using function name as a string. > > Now I cut off from the code a useless pre-invocation, as > this doesnt help anyway, 'cos Octave itself while creating > function objects bails out, when the function is invalid or > undefined. > > Thanks, > Muthu > > PS: Again attaching the code & test case. > PPS: David please let me know if I have missed attribution > and/or citation in comments. Muthu, >From the programs prespective inline and function handles aren't any different. There was also a small bug in the string function handling as the created function was never cleared. Finally you should use the unique_symbol_name function to ensure that you don't accidentally create a function with the same name. It seems you mixed up the way to handle string and inline function calls. Also, I agree with Paul. User functions should handle vector arguments, and so I changed the way the function works to handle a scalar and a vector at a time to reduce the number of calls to feval. You should also be careful with the use of "int" rather than octave_idx_type to allow future operation of your function on 64-bit platforms. The help should also start with a one sentence description of the function as the indexing code in octave-forge and the lookfor extracts this first sentence as the description. I converted the help string to be more in the style of other octave functions. Finally, it is an octave standard to call C++ files with an extension .cc. If you don't then some of the automatic scripts in octave and octave-forge won't index your function if you include it there. I added some test code to prove it all works. Run "test outer.cc". Where is this targeted at? Octave core or octave-forge? If its the core, then you should probably post future stuff to maintainers so its seen as something to go in the core. Any comments? Cheers David --------------080706000203030102000206 Content-Type: text/x-c++src; name="outer.cc" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="outer.cc" /* * (C) 2006, September, Muthiah Annamalai. <[email protected]> * An implementation of the 'outer'-product function as specified in the * octave-projects page, at www.octave.org. * * This program 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 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include<iostream> #include<octave/oct.h> #include<octave/parse.h> #include<octave/dynamic-ld.h> #include<octave/oct-map.h> #include<octave/oct-stream.h> #include<octave/ov.h> #include<octave/parse.h> #include<octave/Matrix.h> #include<octave/ov-cx-mat.h> #include<octave/ov-list.h> #include<octave/ov-base-mat.h> #include<octave/quit.h> #include<octave/error.h> inline static bool is_vector(octave_value arg) { return ((arg.is_matrix_type() && !arg.is_char_matrix() && (arg.columns()==1 || arg.rows()==1)) ? true : false); } DEFUN_DLD(outer,args,, "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {@var{outer_product} =} outer (@var{x},@var{y})\n\ @deftypefnx {Loadable Function} {@var{outer_product} =} outer (@var{x},@var{y},@var{@@f})\n\ @deftypefnx {Loadable Function} {@var{outer_product} =} outer (@var{x},@var{y},@var{\"f\"})\n\ \n\ Returns the outer product of @var{x} and @var{y}. Both @var{x} and @var{y}\n\ must be vectors. @code{outer} returns a @var{m}-by-@var{n} matrix, where\n\ @var{m} is the length of @var{x} and @var{n} is the length of @var{y}.\n\ \n\ If an optional third argument is supplied, it is used to define a function\n\ that is evaluated as @code{@var{f}(@var{x}(@var{i}),@var{y}(@var{j}))} for\n\ the (@var{i}, @var{j})-th element of return matrix. The function can be\n\ defined as a function handle, inline function or string and must accept two\n\ arguments with the second argument being a vector. If a function is not\n\ provided, '*' is used as the default. An example of the use of @code{outer}\n\ is\n\ \n\ @example\n\ outer(@var{[1.0 2.0 3.0]},@var{[2.0 3.0 4.0]},@@gcd)\n\ @end example\n\ \n\ which computes a 3-by-3 matrix with element element being the GCD of the\n\ corresponding x and y elements of the matrix\n\ @end deftypefn") { octave_idx_type m=0, n=0, aLength=0; ColumnVector cv[2]; bool function_present=false; octave_function *func=NULL; octave_value_list erval; const char *func_name=NULL; std::string func_n; bool is_commutative=false; aLength=args.length(); if(aLength < 2) { error("Usage: outer(VecX,VecY,opt:function)"); return erval; } if(!(is_vector(args(0)) || is_vector(args(1)))) { error("Usage: outer(VecX,VecY,opt:function);\n Invalid argument arg- [1 or 2]Expected Row/Column Vector"); return erval; } /* * hope to use commutativity of the operators someday */ if(aLength>=3) { function_present=true; is_commutative=false; if(args(2).is_function_handle() || args(2).is_inline_function()) func=args(2).function_value(); else if ( args(2).is_string() ) { func_n = unique_symbol_name ("__outer_fcn_"); std::string fname = "function z = "; fname.append (func_n); fname.append ("(x, y) z = "); func=extract_function(args(2),"outer", func_n, fname, "(x,y); endfunction"); } else { error("3rd Argument need to be a function. See 'help outer' for more details."); return octave_value(-1); } if (error_state || !func) { error("Cannot obtain function handle from inline or user-defined or dynamic loading."); return octave_value(-1); } } cv[0]=ColumnVector(args(0).vector_value()); cv[1]=ColumnVector(args(1).vector_value()); m=cv[0].length(); n=cv[1].length(); Matrix rmat(m,n); if(function_present && func!=NULL) { octave_value_list ovl; ovl(1) = cv[1]; for(int itr=0;itr<m;itr++) { ovl(0)=cv[0].elem(itr); octave_value_list ret = feval(func, ovl); if(error_state) { error("Exception: while evaluating %s\n", func_name); return erval; } ColumnVector cret = ColumnVector (ret(0).vector_value(false, true)); for(int icol=0;icol<n;icol++) { OCTAVE_QUIT; rmat.elem(itr,icol)=cret(icol); } } if(func_n.length() > 0) { // We have a string function name. Dealloc temp func clear_function (func_n); } } else { /* do a simple product */ rmat=cv[0]*cv[1].transpose(); } return octave_value(rmat); } /* Make command: g++ -fpic outer.cpp -shared -o outer.oct -Wall -ggdb -Wall -Wunused -Wconversion -fno-exceptions -DDEBUG=1 `mkoctfile -p INCFLAGS` */ /* %!shared a,b %! a = [1:3]'; %! b = [1:3]; %!assert(outer(a,b),[1,2,3;2,4,6;3,6,9]); %!test %! f = @(x,y) x + y; %! assert(outer(a,b,f),[2,3,4;3,4,5;4,5,6]); %!test %! g = inline('x - y'); %! assert(outer(a,b,g),[0,-1,-2;1,0,-1;2,1,0]); %!function z = h (x,y) %! z = x * y; %!assert(outer(a,b,'h'),[1,2,3;2,4,6;3,6,9]); */ --------------080706000203030102000206 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Octave-sources mailing list [email protected] https://www.cae.wisc.edu/mailman/listinfo/octave-sources --------------080706000203030102000206--