Path: news.mathworks.com!not-for-mail
From: "Sven " <sven.holcombe@gmail.deleteme.com>
Newsgroups: comp.soft-sys.matlab
Subject: Re: eval, feval, global
Date: Thu, 27 Mar 2008 04:51:25 +0000 (UTC)
Organization: The MathWorks, Inc.
Lines: 143
Message-ID: <fsf94d$lqs$1@fred.mathworks.com>
References: <fsebf0$43u$1@fred.mathworks.com> <fsf3ss$e2e$1@fred.mathworks.com> <fsf7da$g1$1@fred.mathworks.com>
Reply-To: "Sven " <sven.holcombe@gmail.deleteme.com>
NNTP-Posting-Host: webapp-05-blr.mathworks.com
Content-Type: text/plain; charset="ISO-8859-1"
Content-Transfer-Encoding: 8bit
X-Trace: fred.mathworks.com 1206593485 22364 172.30.248.35 (27 Mar 2008 04:51:25 GMT)
X-Complaints-To: news@mathworks.com
NNTP-Posting-Date: Thu, 27 Mar 2008 04:51:25 +0000 (UTC)
X-Newsreader: MATLAB Central Newsreader 1326470
Xref: news.mathworks.com comp.soft-sys.matlab:459399


"Sven " <sven.holcombe@gmail.deleteme.com> wrote in message
<fsf7da$g1$1@fred.mathworks.com>...
> "Yuri Geshelin" <geshelin@hotmail.com> wrote in message
> <fsf3ss$e2e$1@fred.mathworks.com>...
> > Thanks to everyone who replied. I agree with John about 
> > GLOBAL.
> > 
> > As for EVAL, as Peter suggested, let me show you my code, 
> > which I found useful. 
> > 
> > (Actually, there are two situations, in which I use EVAL, 
> > but I will start with presenting the 1st one, as it is 
> > perhaps the more controversial.)
> > 
> > Suppose we have 2 arrays of equal length:
> > 
> > a = [15 23 35 43];
> > b = [ 2 11  8  3];
> > 
> > and we need an algorithm, which constructs output array c 
> > as follows:
> > 
> > c = [15 15 <23 repeated 11 times> <35 repeated 8 times> 43 
> > 43 43]
> > 
> > Here is a simple function construct_array1, which 
> > accomplishes this task.
> > 
> > % *************************** top of construct_array1
> > function c = construct_array1(a,b)
> > 
> > c = [];
> > for i = 1 : length(a)
> >     c = [c ones(1,b(i))*a(i)];
> > end
> > 
> > % *************************** end of construct_array1
> > 
> > And here is another function construct_array, which 
> > accomplishes the same task.
> > 
> > % *************************** top of construct_array
> > function c = construct_array(a,b)
> > 
> > if length(a) ~= length(b)
> >     error('arrays a and b should be of equal lengths!')
> > end
> > 
> > k = floor(log10(max(a)))+1;
> > i = floor(log10(max(b)))+1;
> > n = length(a);
> > m = ones(n,1);
> > c = eval(['[' ...
> >     reshape([char([m*'o' m*'n' m*'e' m*'s' m*'(' m*'1' 
> > m*',']) ...
> >     reshape(sprintf(['%' num2str(i) 'd'],b),i,n)' ...
> >     char([m*')' m*'*']) ...
> >     reshape(sprintf(['%' num2str(k) 'd'],a),k,n)' ...
> >     char(m*' ')]',1,n*(k+i+10)) ']']);
> > % *************************** end of construct_array
> > 
> > Think this is crazy? However, let us test both functions:
> > 
> > >> t = cputime; construct_array1(1:10,1000001:1000010); 
> > cputime-t
> > 
> > ans =
> > 
> >      1.1875
> > 
> > >> t = cputime; construct_array(1:10,1000001:1000010); 
> > cputime-t
> > 
> > ans =
> > 
> >      0.4531
> > 
> > (I was afraid that matlab would crash, but it did not.)
> > 
> > This was experimented on
> > 
> > MATLAB Version 7.0.4.365 (R14) Service Pack 2
> > Operating System: Microsoft Windows XP Version 5.1 (Build 
> > 2600: Service Pack 2)
> > Pentuim(R) 4 CPU 3.20 GHz, 1.00 GB of RAM.
> > 
> > My implementation is thus 2.6 times faster than the use of 
> > a loop. 
> > I admit that this can be costly in terms of RAM, because 
> > the text string supplied to eval can 
> > be huge. But in my practice, the arrays are not too long 
> > (way shorter than in the test case). 
> > The cpu time is saved because I call my function many times 
> > in a loop.
> > 
> > Yuri
> > 
> 
> 
> Hi Yuri,
> 
> I haven't tested exactly how much, but I'm sure
> preallocating your result array will significantly speed up
> the non-eval version of the function.
> 
> Eg:
> 
> startIdx = 1;
> c = zeros(1,sum(b));
> for i = 1:length(b)
>     c((0:b(i)-1) + startIdx) = ones(1,b(i))*a(i);
>     startIdx = startIdx + b(i);
> end
> 
> And I'm sure this can be improved further still.

Well I took the couple of mins to test this. I stand
corrected. My function is:

startIdx = 1;
c = zeros(1,sum(b));
for i = 1:length(b)
    c((0:b(i)-1) + startIdx) = a(i);
    startIdx = startIdx + b(i);
end

Running above function 100 times:
>> tic; for i=1:100, temp_function(1:12,500000:500011); end, toc
Elapsed time is 44.180691 seconds.

Running with the eval version you posted:
>> tic; for i=1:100, temp_function(1:12,500000:500011); end, toc
Elapsed time is 18.499473 seconds.

Still much faster avoiding the loop...

Cheers,
Sven.