Reputation: 1490
I am trying to write an efficient code to perform circular shift which I need to implement it on multiple times on big matrices during my data processing.
On my first trial, compiler throws some exception and it seems that I may be trying to access matrix element outside its size and I have no idea what is going on wrong.
1) I am also using Armadillo lib
which has "mat"
definition.
2) I intend to shift it by row and/ or column.
Here is my try:
#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;
}
It compiles fine. However, when I try to run, Visual studio throws following error:
Unhandled exception at 0x3FF00000 in Circshift_Example.exe: 0xC0000005: Access violation (parameters: 0x00000008).
I get another error in visual studio console, which complains:
error: Mat::init(): requested size is too large
Update: FINAL SOLUTION I am posting my code as it may be useful for some users.
Please note that I am using "Armadillo" library to create matrix. One can replace Armadillo "mat" class wwith their own matrix class.
Please up-vote if you use this code.
#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;
}
Upvotes: 0
Views: 1514
Reputation: 721
The main error here is that you pass pointers to mat
type objects to the circshift()
function (the out
and in
argument, but then use these arguments as arrays to mat
. The following line is not interpreted as you think
out[iOutputInd] = in[iInputInd];
because out
and in
are not mat
objects. They are pointers to mat
objects, so the compiler will interpret in
and out
as being pointer to arrays of mat
and index these arrays, copying a non-existant mat
from in[...] to another non-existant location.
One simple way to fix that is to use references instead of pointers to pass the mat
objects, i.e.:
template<class ty> void circshift(ty& out, const ty& in, int xdim, int ydim, int xshift, int yshift)
{
...
}
and call it in _tmain using:
circshift(a_out, a, xdim, ydim, xshift, yshift);
Upvotes: 1