我在Rcpp
(C++
R
)中有一个矩阵,它按列顺序存储在内存中。即,它看起来像:
[,1] [,2] [,3] [,4] [,5]
[1,] 1 6 11 16 21
[2,] 2 7 12 17 22
[3,] 3 8 13 18 23
[4,] 4 9 14 19 24
[5,] 5 10 15 20 25
现在,我有一个for
循环,从i = 1
到25
(请记住,它全部为零,但是为了方便,我只是说一个) 。
对于矩阵的每个元素,我想要它的摩尔邻域。对于不在边缘的元素,这很容易。因此,如果我们选择的索引为idx
且方阵的大小为nrow
,那么我们有
leftmid = idx - nrow
lefttop = (idx - nrow) - 1
leftbot = (idx - nrow) + 1
rightmid = idx + nrow
righttop = (idx + nrow) - 1
rightbot = (idx + nrow) + 1
midtop = idx - 1
midbot = idx + 1
但我无法弄清楚如何处理边缘情况。例如,如果idx = 3
,那么我想要邻居:
leftmid = 23
lefttop = 22
leftbot = 24
rightmid = 8
righttop = 7
rightbot = 9
midtop = 2
midbot = 4
在角落情况下也有点复杂。我的目标是减少时间。我目前正在使用双循环运行我的程序,但是速度慢于合理。我想将其更改为单个for
循环以提高性能。
编辑:我意识到left
和right
边界可以通过模数获得。所以3 - 5 %% 25 = 23
。但我仍然有顶边和底边的情况。
答案 0 :(得分:0)
看起来你对“循环”边界条件感兴趣,其中矩阵具有环形拓扑,即顶部环绕到底部,右边环绕到左边。
使用四个循环进行迭代可能更容易,每个循环分别在行和列上,然后分别在邻域的行和列上循环。这样的事情应该有效:
int mooreNeighbors[3][3];
int nRows = 5;
int nCols = 5;
// Loop over the rows and columns of the matrix
for (int i = 0; i < nRows; ++i) {
for (int j = 0; j < nCols; ++j) {
// Loop over the cyclic Moore neighborhood
for (int mnI = 0; mnI < 3; ++mnI) {
for (int mnJ = 0; mnJ < 3; ++mnJ) {
// Sub-matrix indices
int subI = (i - mnI - 1) % nRows;
int subJ = (j - mnJ - 1) % nCols;
// Index into column-dominant matrix
int idx = subI + subJ*nRows;
mooreNeighbors[mnI][mnJ] = matrix[idx];
}
}
}
}
我没有尝试过编译,但它应该接近正确和清晰,以纠正任何错误。把它想象成伪代码。
另外,我更倾向于清晰度而不是最优性。例如,您不必在最内层循环中执行所有操作。