matlab中vectorize,How to vectorize a piecewise periodic function in MATLAB?

问题

I've noticed that matlab builtin functions can handle either scalar or vector parameters. Example:

sin(pi/2)

ans =

1

sin([0:pi/5:pi])

ans =

0 0.5878 0.9511 0.9511 0.5878 0.0000

If I write my own function, for example, a piecewise periodic function:

function v = foo(t)

t = mod( t, 2 ) ;

if ( t < 0.1 )

v = 0 ;

elseif ( t < 0.2 )

v = 10 * t - 1 ;

else

v = 1 ;

end

I can call this on individual values:

[foo(0.1) foo(0.15) foo(0.2)]

ans =

0 0.5000 1.0000

however, if the input for the function is a vector, it is not auto-vectorized like the builtin function:

foo([0.1:0.05:0.2])

ans =

1

Is there a syntax that can be used in the definition of the function that indicates that if a vector is provided, a vector should be produced? Or do builtin functions like sin, cos, ... check for the types of their input, and if the input is a vector produce the same result?

回答1:

You need to change your syntax slightly to be able to handle data of any size. I typically use logical filters to vectorise if-statements, as you're trying to do:

function v = foo(t)

v = zeros(size(t));

t = mod( t, 2 ) ;

filt1 = t<0.1;

filt2 = ~filt1 & t<0.2;

filt3 = ~filt1 & ~filt2;

v(filt1) = 0;

v(filt2) = 10*t(filt2)-1;

v(filt3) = 1;

In this code, we've got three logical filters. The first picks out all elements such that t<0.1. The second picks out all of the elements such that t<0.2 that weren't in the first filter. The final filter gets everything else.

We then use this to set the vector v. We set every element of v that matches the first filter to 0. We set everything in v which matches the second filter to 10*t-1. We set every element of v which matches the third filter to 1.

For a more comprehensive coverage of vectorisation, check the MATLAB help page on it.

回答2:

A simple approach that minimizes the number of operations is:

function v = foo(t)

t = mod(t, 2);

v = ones(size(t)) .* (t > 0.1);

v(t < 0.2) = 10*t(t < 0.2) - 1;

end

If the vectors are large, it might be faster to do ind = t < 0.2, and use that in the last line. That way you only search through the array once. Also, the multiplication might be substituted by an extra line with logical indices.

回答3:

I repeatedly hit the same problem, thus I was looking for a more generic solution and came up with this:

%your function definition

c={@(t)(mod(t,2))<0.1,0,...

@(t)(mod(t,2))<0.2,@(t)(10 * t - 1),...

true,1};

%call pw which returns the function

foo=pw(c{:});

%example evaluation

foo([0.1:0.05:0.2])

Now the code for pw

function f=pw(varargin)

for ip=1:numel(varargin)

switch class(varargin{ip})

case {'double','logical'}

varargin{ip}=@(x)(repmat(varargin{ip},size(x)));

case 'function_handle'

%do nothing

otherwise

error('wrong input class')

end

end

c=struct('cnd',varargin(1:2:end),'fcn',varargin(2:2:end));

f=@(x)pweval(x,c);

end

function y=pweval(x,p)

todo=true(size(x));

y=x.*0;

for segment=1:numel(p)

mask=todo;

mask(mask)=logical(p(segment).cnd(x(mask)));

y(mask)=p(segment).fcn(x(mask));

todo(mask)=false;

end

assert(~any(todo));

end

来源:https://stackoverflow.com/questions/27097861/how-to-vectorize-a-piecewise-periodic-function-in-matlab

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值