我正在尝试在MATLAB中使用单个for循环实现BlockLMS。为此,给定一个向量 u ,我试图创建一个表格
U = [u(k) u(k+1) u(k+2) ... u(k+n)
u(k-1) u(k) ... ... u(k+n-1)
... ... ... ... ...
u(k-n) u(k-n+1) ... ... u(k)]
其中 n 是一个常量, k 是一个随每个for循环而变化的变量,始终为k > n
。到目前为止我所取得的成就是:
index = meshgrid(0:-1:1-n)' + meshgrid(1:n);
for i = 2:q
% calculate k
U = u(k + index);
% rest of code goes here
end
虽然它有效,但遗憾的是很慢,并不适合我的需要。有没有更有效的方法来实现这一结果?
答案 0 :(得分:6)
您可以使用toeplitz
toeplitz(20:-1:15,20:25)
ans =
20 21 22 23 24 25
19 20 21 22 23 24
18 19 20 21 22 23
17 18 19 20 21 22
16 17 18 19 20 21
15 16 17 18 19 20
或者,以更通用的方式:
f = @(k,n)toeplitz(k:-1:k-n,k:k+n)
然后您可以编写U=u(f(k,n))
来获取问题中的通用表单。
但请检查一下这是否确实比你的for循环更快。
toeplitz
的内部机制是bsxfun
,所以我猜想除非你在较低级别的c \ fortran中意识到这一点,否则这就好了。检查edit toeplitz
并查看其实施方式......
答案 1 :(得分:4)
这应该有效:
k = 20; % Example k
n = 5; % Example n < k
u = 1:50; % Example vector
[x, y] = meshgrid(0:n,k:-1:k-n);
U = u(x+y) % Use x+y as index
U =
20 21 22 23 24 25
19 20 21 22 23 24
18 19 20 21 22 23
17 18 19 20 21 22
16 17 18 19 20 21
15 16 17 18 19 20
如您所见,左上角是元素编号k
,右上角是元素编号k+n
,左下角是k-n
,右下角是元素{{ 1}}。
答案 2 :(得分:4)
该操作有很多重复。所以,为了利用这种性质,这里有一种使用imagerotate的方法和repmat
屏蔽功能的一点帮助 -
mask = bsxfun(@ge,(1:2*n+1)',n+1:-1:1) & bsxfun(@ge,(2*n+1:-1:1)',1:n+1)
sliced_u = u(k+n:-1:k-n)
repvals = repmat(sliced_u(:),1,n+1)
out = reshape(repvals(mask),n+1,[])
当人们沿着列复制输入u
的柱状版本时,我们可以向右移动一个位置时,可以用来描述所需输出的列。 。剩下的工作是抵消沿着柱子移动的一个位置,这是通过bsxfun
的遮蔽来切断上下三角形区域以给出最终输出。
效果:此问题之前已被利用bsxfun's
中的类似问题,我希望此处有相似的效果数字。
作为另一种方法并直接思考,可以使用bsxfun
来获取2D索引,然后为最终输出索引u
,就像这样 -
out = u(bsxfun(@plus,(k:-1:k-n)',0:n))