How to vectorise the code below
3 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
David Epstein
il 21 Dic 2018
Modificato: Stephen23
il 21 Dic 2018
I have asked about fsurf two or three times on this platform, and received two replies, neither of which extracted me from my difficulties. I have, however, made slow progress. I think I have found one bug in both execution and documentation of fsurf, and whether or not this is really a bug is still under consideration by Mathworks. I have finally succeeded in writing some code that actually outputs an image that seems to be related to what I am aiming at. The code is given the "green light" by the editor, but, when run produces many warnings. These all relate to the complaint that my code does not vectorize. Since the functions concerned are functions of two variables, I am not sure how fsurf would like me to change the code. Here is my code (called SE3):
close all; clear all; %#ok
R = 5; % centre of square is at r=R, z=0, where r is radial coord in (x,y)
%vertices of square in (x,z) plane.
A = [1,1,-1,-1,1;1,-1,-1,1,1];
figure; hold;
for x = 1:4
funx = @(ang,s) cos(ang)*(R + [cos(ang),sin(ang)]*(s*A(:,x)...
+ (1-s)*A(:,x+1)));
funy = @(ang,s) sin(ang)*(R + [cos(ang),sin(ang)]*(s*A(:,x)...
+ (1-s)*A(:,x+1)));
funz = @(ang,s)[-sin(ang),cos(ang)]*(s*A(:,x)+(1-s)*A(:,x+1));
fsurf(funx,funy,funz,[0,2*pi,0,1]);
end
hold off;
Here is the warning (only the first few lines of many warnings)
Warning: Function behaves unexpectedly on array inputs. To improve performance, properly vectorize
your function to return an output with the same size and shape as the input arguments.
> In matlab.graphics.function.ParameterizedFunctionSurface>checkVectorization
In matlab.graphics.function.ParameterizedFunctionSurface/set.XFunction
In matlab.graphics.function.ParameterizedFunctionSurface
In fsurf>singleFsurf (line 263)
In fsurf>@(f1,f2,f3)singleFsurf(cax,{f1,f2,f3},extraOpts,args) (line 236)
In fsurf>vectorizeFsurf (line 236)
In fsurf (line 200)
In SE3 (line 12)
8 Commenti
Stephen23
il 21 Dic 2018
Modificato: Stephen23
il 21 Dic 2018
@David Epstein: personally I have never found a use for fsurf and fplot and all those other magical plotting functions. I like to know what my data is doing, which means using meshgrid or ndgrid and generating the values myself. Don't feel demoralized, just chalk it up to experience.
" It's still a puzzle to me how I would use regular functions.... In my code there are implicitly 12 distinct functions. A factor 4 for x=1:4 ..."
One way would be to note that x (and possibly others) are also variables: you don't just have a function of two variables, but a function of three (or four or five) variables, so you can write a function that with those input arguments:
function out = funX(ang,S,x,...)
out = ...
end
and then within the code you can specify those values explicitly or use define a parametrized function, e.g. within your loop:
fx = @(a,s)funX(a,s,x);
...
fsurf(fx, ...)
Thus it would be easy to bring it down to two functions by specifying the X/Y functions and inputting a function handle to distinguish:
function out = funXY(ang,S,x,fun)
out = fun(ang) .* ...;
end
So then you can specify the first factor when the function is parameterized:
fx = @(a,s)funXY(a,s,x,@cos);
fy = @(a,s)funXY(a,s,x,@sin);
...
fsurf(fx, fy, ...)
Risposta accettata
Stephen23
il 21 Dic 2018
Here are some vectorized versions of your functions:
R = 5;
A = [1,1,-1,-1,1;1,-1,-1,1,1];
B = cat(3,A(1,:),A(2,:));
for x = 1:4
% Vectorized:
fz = @(ang,s) sum(cat(3,-sin(ang),+cos(ang)).*(s.*B(1,x,:)+(1-s).*B(1,x+1,:)),3);
fa = @(ang,s) sum(cat(3,+cos(ang),+sin(ang)).*(s.*B(1,x,:)+(1-s).*B(1,x+1,:)),3);
fx = @(ang,s) cos(ang).*(R + fa(ang,s));
fy = @(ang,s) sin(ang).*(R + fa(ang,s));
% Original:
funx = @(ang,s) cos(ang)*(R + [cos(ang),sin(ang)]*(s*A(:,x) + (1-s)*A(:,x+1)));
funy = @(ang,s) sin(ang)*(R + [cos(ang),sin(ang)]*(s*A(:,x) + (1-s)*A(:,x+1)));
funz = @(ang,s)[-sin(ang),cos(ang)]*(s*A(:,x)+(1-s)*A(:,x+1));
% Compare:
new = fx(G,S); % can be called by FSURF.
old = arrayfun(funx,G,S);
all(abs(new(:)-old(:))<1e-10)
end
0 Commenti
Più risposte (0)
Vedere anche
Categorie
Scopri di più su Surface and Mesh Plots in Help Center e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!