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() 函数(outin 参数,但随后使用这些参数作为 mat 的数组。下面这行并不像你想的那样被解释

out[iOutputInd] = in[iInputInd];

因为 outin 不是 mat 对象。它们是指向 mat 对象的指针,因此编译器会将 inout 解释为指向 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);