C/C++:矩阵循环移位
C/C++: circular shift on matrices
我正在尝试编写一个高效的代码来执行循环移位,在我的数据处理过程中,我需要在大矩阵上多次实现它。
在我的第一次试用中,编译器抛出了一些异常,似乎我可能正在尝试访问超出其大小的矩阵元素,但我不知道发生了什么问题。
1) 我也在使用具有 "mat"
定义的 Armadillo lib
。
2) 我打算按行和/或列移动它。
这是我的尝试:
#include "stdafx.h"
#include <vector>
#include <iostream>
#include "C:\Users\kumar\Documents\Visual Studio 2012\UserLibs\armadillo-3-910-0\include\armadillo"
#include <stdlib.h> /* srand, rand */
using namespace arma;
template<class ty>
void circshift(ty *out, const ty *in, int xdim, int ydim, int xshift, int yshift)
{
int iOutputInd, iInputInd, ii, jj;
for (int i =0; i < xdim; i++)
{
ii = (i + xshift) % xdim;
for (int j = 0; j < ydim; j++)
{
jj = (j + yshift) % ydim;
iOutputInd = ii * ydim + jj;
iInputInd = i * ydim + j;
std::cout << " iOutputInd --> " << iOutputInd << " ; iInputInd -->" << iInputInd << "\n";
out[iOutputInd] = in[iInputInd]; // EXCEPTION BEING THROWN HERE
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
//a = [1 2 3; 4 5 6; 7 8 9];
mat a, a_out; // "mat" defined in C++ lib Armadillo
a << 1 << 2 << 3 << endr
<< 4 << 5 << 6 << endr
<< 7 << 8 << 9 <<endr;
a.reshape(3,3);
//a.print();
a_out = a;
int xdim = 3; int ydim = 3; int xshift = 1; int yshift = 0;
circshift(&a_out, &a, xdim, ydim, xshift, yshift);
a_out.print();
return 0;
}
编译正常。但是,当我尝试 运行 时,Visual studio 抛出以下错误:
Unhandled exception at 0x3FF00000 in Circshift_Example.exe: 0xC0000005: Access violation (parameters: 0x00000008).
我在 visual studio 控制台中收到另一个错误,它抱怨:
error: Mat::init(): requested size is too large
更新:最终解决方案
我发布我的代码,因为它可能对某些用户有用。
请注意,我正在使用 "Armadillo" 库来创建矩阵。可以用自己的矩阵 class.
替换 Armadillo "mat" class
如果您使用此代码,请点赞。
#include "stdafx.h"
#include "armadillo-3-910-0\include\armadillo"
using namespace arma;
template<class ty>
void circshift(ty& out, const ty& in, int xshift, int yshift)
{
int iOutputInd, iInputInd, ii, jj;
int ydim = in.n_cols;
int xdim = in.n_rows;
for (int j =0; j < ydim; j++)
{
jj = (j + yshift) % ydim;
if (jj <0) jj = jj + ydim;
for (int i = 0; i < xdim; i++)
{
ii = (i + xshift) % xdim;
if (ii <0) ii = ii + xdim;
out[jj * xdim + ii] = in[j * xdim + i];
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
//a = [1 2 3; 4 5 6; 7 8 9];
mat a, a_out;
a << 1 << 2 << 3 << endr
<< 4 << 5 << 6 << endr
<< 7 << 8 << 9 <<endr;
a.reshape(3,3);
a_out = a;
int xshift = 1; int yshift = 0;
circshift(a_out, a, xshift, yshift);
a_out.print();
xshift = 1; yshift = -1;
circshift(a_out, a, xshift, yshift);
a_out.print();
return 0;
}
这里的主要错误是您将指向 mat
类型对象的指针传递给 circshift()
函数(out
和 in
参数,但随后使用这些参数作为 mat
的数组。下面这行并不像你想的那样被解释
out[iOutputInd] = in[iInputInd];
因为 out
和 in
不是 mat
对象。它们是指向 mat
对象的指针,因此编译器会将 in
和 out
解释为指向 mat
数组的指针并索引这些数组,复制一个不存在的 mat
从 [...] 到另一个不存在的位置。
解决这个问题的一个简单方法是使用引用而不是指针来传递 mat
对象,即:
template<class ty> void circshift(ty& out, const ty& in, int xdim, int ydim, int xshift, int yshift)
{
...
}
并在 _tmain 中调用它:
circshift(a_out, a, xdim, ydim, xshift, yshift);
我正在尝试编写一个高效的代码来执行循环移位,在我的数据处理过程中,我需要在大矩阵上多次实现它。
在我的第一次试用中,编译器抛出了一些异常,似乎我可能正在尝试访问超出其大小的矩阵元素,但我不知道发生了什么问题。
1) 我也在使用具有 "mat"
定义的 Armadillo lib
。
2) 我打算按行和/或列移动它。
这是我的尝试:
#include "stdafx.h"
#include <vector>
#include <iostream>
#include "C:\Users\kumar\Documents\Visual Studio 2012\UserLibs\armadillo-3-910-0\include\armadillo"
#include <stdlib.h> /* srand, rand */
using namespace arma;
template<class ty>
void circshift(ty *out, const ty *in, int xdim, int ydim, int xshift, int yshift)
{
int iOutputInd, iInputInd, ii, jj;
for (int i =0; i < xdim; i++)
{
ii = (i + xshift) % xdim;
for (int j = 0; j < ydim; j++)
{
jj = (j + yshift) % ydim;
iOutputInd = ii * ydim + jj;
iInputInd = i * ydim + j;
std::cout << " iOutputInd --> " << iOutputInd << " ; iInputInd -->" << iInputInd << "\n";
out[iOutputInd] = in[iInputInd]; // EXCEPTION BEING THROWN HERE
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
//a = [1 2 3; 4 5 6; 7 8 9];
mat a, a_out; // "mat" defined in C++ lib Armadillo
a << 1 << 2 << 3 << endr
<< 4 << 5 << 6 << endr
<< 7 << 8 << 9 <<endr;
a.reshape(3,3);
//a.print();
a_out = a;
int xdim = 3; int ydim = 3; int xshift = 1; int yshift = 0;
circshift(&a_out, &a, xdim, ydim, xshift, yshift);
a_out.print();
return 0;
}
编译正常。但是,当我尝试 运行 时,Visual studio 抛出以下错误:
Unhandled exception at 0x3FF00000 in Circshift_Example.exe: 0xC0000005: Access violation (parameters: 0x00000008).
我在 visual studio 控制台中收到另一个错误,它抱怨:
error: Mat::init(): requested size is too large
更新:最终解决方案 我发布我的代码,因为它可能对某些用户有用。
请注意,我正在使用 "Armadillo" 库来创建矩阵。可以用自己的矩阵 class.
替换 Armadillo "mat" class如果您使用此代码,请点赞。
#include "stdafx.h"
#include "armadillo-3-910-0\include\armadillo"
using namespace arma;
template<class ty>
void circshift(ty& out, const ty& in, int xshift, int yshift)
{
int iOutputInd, iInputInd, ii, jj;
int ydim = in.n_cols;
int xdim = in.n_rows;
for (int j =0; j < ydim; j++)
{
jj = (j + yshift) % ydim;
if (jj <0) jj = jj + ydim;
for (int i = 0; i < xdim; i++)
{
ii = (i + xshift) % xdim;
if (ii <0) ii = ii + xdim;
out[jj * xdim + ii] = in[j * xdim + i];
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
//a = [1 2 3; 4 5 6; 7 8 9];
mat a, a_out;
a << 1 << 2 << 3 << endr
<< 4 << 5 << 6 << endr
<< 7 << 8 << 9 <<endr;
a.reshape(3,3);
a_out = a;
int xshift = 1; int yshift = 0;
circshift(a_out, a, xshift, yshift);
a_out.print();
xshift = 1; yshift = -1;
circshift(a_out, a, xshift, yshift);
a_out.print();
return 0;
}
这里的主要错误是您将指向 mat
类型对象的指针传递给 circshift()
函数(out
和 in
参数,但随后使用这些参数作为 mat
的数组。下面这行并不像你想的那样被解释
out[iOutputInd] = in[iInputInd];
因为 out
和 in
不是 mat
对象。它们是指向 mat
对象的指针,因此编译器会将 in
和 out
解释为指向 mat
数组的指针并索引这些数组,复制一个不存在的 mat
从 [...] 到另一个不存在的位置。
解决这个问题的一个简单方法是使用引用而不是指针来传递 mat
对象,即:
template<class ty> void circshift(ty& out, const ty& in, int xdim, int ydim, int xshift, int yshift)
{
...
}
并在 _tmain 中调用它:
circshift(a_out, a, xdim, ydim, xshift, yshift);