Re: outer product implementation
Muthiah Annamalai <[email protected]> Tue, 12 Sep 2006 17:40:06 -0500
| Newsgroups | gmane.comp.gnu.octave.sources |
|---|---|
| Message-ID | <1158100806.21542.15.camel@localhost> |
--=-Ulbj3VRcRR9ncYEYzVD9
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
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.
On Mon, 2006-09-11 at 21:40 +0200, David Bateman wrote:
> Muthiah Annamalai wrote:
>
> > David,
> > I think I didnt mention the kind of functionality I wanted:
> > To evaluate functions when
> >
> > 1. Passed by @ sign
> > 2. Passed by function name (string)
> > 3. Passed by inline function code
> >
> >
> > Now the code you point out to me handles the inline function code.
> >
> > But I was actually mentioning #2 in the list.
> >
>
> Check again. There is functionally no difference between inline and
> function handles in an oct-file (as in fact one class is derived from
> the other). So the function handles and inline functions are both
> handled by the first couple of lines. String args are handled by the
> rest of the code.
>
> > I think I will have to use some way to load the function and
> > get a octave_function handle to it, as feval() of this might
> > make the process slower than it need to be.
> >
> > So Im working on adding the #2 and #3 using your suggested code in
> > (quad.cc).
>
> Use the code in the message, as the code in quad.cc assumes that the
> function has a single input and output argument..
>
> D.
>
> >
> > Thanks
> > Muthu
>
--=-Ulbj3VRcRR9ncYEYzVD9
Content-Disposition: attachment; filename=outer.cpp
Content-Type: text/x-c++src; name=outer.cpp; charset=UTF-8
Content-Transfer-Encoding: 7bit
/*
* (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"
"function outer(VecX,VecY,opt:function)\n"
"Return a @var{M}x@var{N} matrix with @var{f}(@var{x},@var{y}) evaluated at x,y position\n"
"for each @var{x},@var{y} in Vector @var{X},Vector @var{Y} respectively\n"
"If function is not provided, use '*' as default operation\n"
"A function can be provided using argument @var{f} \n"
"using reference operator (@@) or the name of function or inline functions.\n"
"\n"
"example: outer(@var{[1.0 2.0 3.0]},@var{[2.0 3.0 4.0]},@@gcd)\n"
"compute the 3x3 matrix with each element in it being the\n"
"GCD of the corresponding x and y elements of the matrix\n"
"\n"
"@end deftypefn\n"
"@seealso{}")
{
int 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_inline_function())
{
std::string fname;
func_n = unique_symbol_name ("__fcn_");
fname = "function z = ";
fname.append (func_n);
fname.append ("(x, y) z = ");
octave_stdout << "IS INLINE: "<< fname << std::endl;
func = extract_function (args(0), "outer", func_n, fname,"(x, y); endfunction");
}
else if(args(2).is_function_handle())
{
func=args(2).function_value();
}
else if ( args(2).is_string() )
{
std::string fname;
fname = "function z = ";
fname.append (args(2).string_value());
fname.append ("(x, y) z = ");
octave_stdout << fname << std::endl;
func=extract_function(args(2),"outer",args(2).string_value(), \
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);
octave_value_list ovl;
if(function_present && func!=NULL)
{
/* FIXME: <Vectorize Code>
* Paul says do this thing as a single loop.
* Iterate over Columns, taking one full column at a time,
* and save the result on the columns of the matrix.
* Atleast this is possible for builtins that take arguments
* over columns/rows, if not user defined functions.
*/
for(int itr=0;itr<m;itr++)
for(int icol=0;icol<n;icol++)
{
OCTAVE_QUIT;
ovl(0)=cv[0].elem(itr);
ovl(1)=cv[1].elem(icol);
rmat.elem(itr,icol)=feval(func,ovl)(0).double_value();
if(error_state)
{
error("Exception: while evaluating %s with arguments %g %g\n",func_name,cv[0].elem(itr),cv[1].elem(icol));
return erval;
}
}
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`
*/
--=-Ulbj3VRcRR9ncYEYzVD9
Content-Disposition: attachment; filename=outertest.m
Content-Type: text/x-octave; name=outertest.m; charset=UTF-8
Content-Transfer-Encoding: 7bit
#! /usr/bin/octave -q
%outer
disp('Help on Outer')
help outer
pause
disp('Product- testing ;-) Imean this * product')
outer([1 2],[1 2 3 4])
outer([1],[1 2 3])
outer([1 2 3],[1])
outer([1 2 3],[1 2 3])
%outer([1],[2]) %error this is caught.
pause
disp('Functions being Invoked')
pause
disp('Min')
outer(rand(1,10),rand(1,10),@min)
outer(rand(1,4),rand(1,4),"min")
outer(rand(1,2),rand(1,2),'min')
disp('IsEqual')
outer([1 2],[1 2 3 4],@isequal)
disp('Max')
outer([1],[1 2 3],@max)
disp('GCD ')
outer([1.0 2.0 3.0],[2.0 3.0 4.0],@gcd)
outer([1.0 2.0 3.0],[2.0 3.0 4.0],'gcd')
outer([14 20 35 40],[7],@gcd)
disp('Square Matrix')
outer([1:5],[1:5])
disp('One arg scalar other vector')
outer(3,[1:5])
outer([1:5],3)
disp('functions that dont return an argument! ')
try
outer([14 20 35 40],[7],@disp) %functions that dont return an argument!
catch
disp('Exception')
end
disp('non-existent functions throw errors at Octave prompt itself.');
try
outer([14 20 35 40],[7],@bwand) %non-existent functions throw errors at Octave prompt itself.
catch
disp('Exception')
end
try
disp('Both Scalar')
outer([1],[2]) %error
catch
disp('Exception')
end
--=-Ulbj3VRcRR9ncYEYzVD9
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
--=-Ulbj3VRcRR9ncYEYzVD9--