On Mon, Sep 09, 2002 at 01:40:45PM -0500, John W. Eaton wrote:

> On 8-Sep-2002, John W. Eaton <

[hidden email]> wrote:

>

> | On 8-Sep-2002, Paul Kienzle <

[hidden email]> wrote:

> |

> | | I am surprised that

> | | stat("test.jpg").size

> | | returns the entire structure instead of just the size element. Is this

> | | behaviour expected?

> |

> | No, it looks like a bug. I'll try to fix this soon.

>

> I've checked in the following patch.

>

> Note the comment I added:

>

> // XXX FIXME XXX -- Note that if a function call returns multiple

> // values, and there is further indexing to perform, then we are

> // ignoring all but the first value. Is this really what we want to

> // do? If it is not, then what should happen for stat("file").size,

> // for exmaple?

>

> Currently, some functions (like stat) return multiple values even when

> nargout is only 0 or 1, and then the extra values are simply ignored.

> I think it's easier to implement some of these functions if that's the

> way things work. I suppose we could tighten up the error checking

> here if we required functions to only return as many values as

> requested, but that seems like a lot of extra work to do. Or, we

> could only allow further indexing when nargout is 0 or 1. What do you

> think?

The only place I force 2 output arguments is in the filter design functions

since a filter with only A and not B doesn't make any sense. Within

the function I check for nargout == 2, or generate an error.

Since the need to do otherwise is rare and since you can force it if you

need it by generating your own errors, I think the interpreter should use

only as many return values as it needs, at least in scripts.

For compiled functions, I would prefer having the interpreter allocate the

slots it needs for the return values and pass a handle for it to the

interpreted function. I noticed in profiling that a big chunk of time is

spent in class constructors and destructors. Modifying handles rather than

returning objects from functions should reduce this overhead. Returning

pointers to octave values rather than copying octave values to an array

of octave_values would reduce overhead even further.

Try the following using the attached churn.cc:

octave:1> tic; churn; toc

ans = 0.15586

octave:2> tic; churn; toc

ans = 0.11828

octave:3> tic; nochurn; toc

ans = 0.012887

octave:4> tic; noovchurn; toc

ans = 0.0094780

I'm guessing these changes are too big to go in before 2.2.

- Paul

---- churn.cc -----

#include <octave/oct.h>

octave_value_list churn(int n)

{

octave_value_list ret;

ret(0) = octave_value(1.0);

return ret;

}

DEFUN_DLD(churn,args,,"test octave_value_list return")

{

for (int i=1; i < 10000; i++)

{

octave_value_list ret = churn(1);

}

return octave_value_list();

}

int nochurn(int n, octave_value ret[])

{

if (n > 0)

{

ret[0] = octave_value(1.0);

return 1;

}

else

return 0;

}

DEFUN_DLD(nochurn,args,,"test array of octave values")

{

for (int i=1; i < 10000; i++)

{

octave_value ret[1];

int rets = nochurn(1,ret);

}

return octave_value_list();

}

int noovchurn(int n, octave_value* ret[])

{

if (n > 0)

{

ret[0] = new octave_value(1.0);

return 1;

}

else

return 0;

}

DEFUN_DLD(noovchurn,args,,"test array of pointers to ovs")

{

for (int i=1; i < 10000; i++)

{

octave_value* ret[1];

int rets = noovchurn(1,ret);

if (rets) delete ret[0];

}

return octave_value_list();

}