Related
Basically I wrote code to simulate one encoded data vector over a AWGN channel. The simulation but only works once. So I would like to create multiple objects or find a way to run the code multiple times depending on int N (for example int N = 1000000; in my case), so that I can calculate the BER (bit error rate).
I haven't found an elegant way to do that yet though...
I hope you understand my question.
Do you need more information?
Thank you!!
#include <iostream>
#include "encode.h"
#include "awgn.h"
#include "decode.h"
using namespace Eigen;
int main()
{
std::string code = "Hamming";
int dim_u, dim_mat_col, dim_mat_row, dim_mat_col_H, dim_mat_row_H;
MatrixXi P;
if (code == "Hamming")
{
dim_u = 4; // can also call it "k"
dim_mat_col = 7; // also serves as dim of x and y, or simply n
dim_mat_row = 4;
dim_mat_col_H = dim_mat_col;
dim_mat_row_H = dim_mat_col - dim_mat_row;
P = MatrixXi::Zero(dim_u, dim_mat_col - dim_u);
P << 1, 1, 0,
0, 1, 1,
1, 1, 1,
1, 0, 1;
}
if (code == "BCH")
{
dim_u = 7;
dim_mat_col = 15; // also serves as dim of x and y, or simply n
dim_mat_row = 7;
dim_mat_col_H = dim_mat_col;
dim_mat_row_H = dim_mat_col - dim_mat_row;
P = MatrixXi::Zero(dim_u, dim_mat_col - dim_u);
P << 1, 1, 1, 0, 1, 0, 0, 0,
0, 1, 1, 1, 0, 1, 0, 0,
0, 0, 1, 1, 1, 0, 1, 0,
0, 0, 0, 1, 1, 1, 0, 1,
1, 1, 1, 0, 0, 1, 1, 0,
0, 1, 1, 1, 0, 0, 1, 1,
1, 1, 0, 1, 0, 0, 0, 1;
}
if (code == "Golay")
{
dim_u = 12;
dim_mat_col = 24; // also serves as dim of x and y, or simply n
dim_mat_row = 12;
dim_mat_col_H = dim_mat_col;
dim_mat_row_H = dim_mat_col - dim_mat_row;
P = MatrixXi::Zero(dim_u, dim_mat_col - dim_u);
P << 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1,
0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0,
0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1,
1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0,
1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1,
1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0,
1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0,
0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1,
0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1,
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1;
}
int N = 1000000; // number of simulations
bool c_hat_minus_c = 0;
int val = 0;
Encode vec(dim_u, dim_mat_row, dim_mat_col);
awgn channel(dim_mat_col);
Decode dec(dim_mat_col, dim_mat_row_H, dim_mat_col_H, P);
vec.encodeDataVector(dim_u, dim_mat_col, P);
// std::cout << "modulated x: " << vec.x << std::endl;
channel.addGausian(vec.x);
// std::cout << channel.y << std::endl;
c_hat_minus_c = dec.decodingalg(6000, channel.y, P, vec.x); // check if codeword is received correctly
// std::cout << channel.y << std::endl;
// std::cout << "val: " << val << std::endl;
}
If I wrap the stack allocated objects in a for loop like this:
for (int i = 0; i < N; i++)
{
Encode vec(dim_u, dim_mat_row, dim_mat_col);
awgn channel(dim_mat_col);
Decode dec(dim_mat_col, dim_mat_row_H, dim_mat_col_H, P);
vec.encodeDataVector(dim_u, dim_mat_col, P);
// std::cout << "modulated x: " << vec.x << std::endl;
channel.addGausian(vec.x);
// std::cout << channel.y << std::endl;
c_hat_minus_c = dec.decodingalg(6000, channel.y, P, vec.x); // check if codeword is received correctly
// std::cout << channel.y << std::endl;
// std::cout << "val: " << val << std::endl;
}
The program breaks and says:
/usr/include/eigen3/Eigen/src/Core/CommaInitializer.h:97: Eigen::CommaInitializer& Eigen::CommaInitializer::operator,(const Eigen::DenseBase&) [with OtherDerived = Eigen::Matrix<int, -1, -1>; XprType = Eigen::Matrix<int, -1, -1>]: Assertion `(m_col + other.cols() <= m_xpr.cols()) && "Too many coefficients passed to comma initializer (operator<<)"' failed.
Edit:
so I basically found out that it braks in encode.cpp
the second time it tries to initialize the Matrix G_
#include <iostream>
#include "encode.h"
#include "awgn.h"
#include <cstdlib> // rand and srand
#include <ctime> // For the time function
using namespace std;
using namespace Eigen;
Encode::Encode(int dim_u, int dim_mat_row, int dim_mat_col) //(7,4) Hamming code only up to now
{
// if (code == "Hamming")
// dim_u = 4;
// dim_mat_col = 7;
// dim_mat_row = 4;
u_ = RowVectorXi::Zero(dim_u);
G_ = MatrixXi::Zero(dim_mat_row, dim_mat_col);
}
void Encode::encodeDataVector(int dim_u, int dim_mat_col, MatrixXi &P)
{
// Get the system time.
unsigned seed = time(0);
// Seed the random number generator.
srand(seed);
for (int i = 0; i < dim_u; i++)
{
u_(i) = rand() % 2; // only zeros and ones
}
// cout << u_ << endl << endl;
MatrixXi I;
// I = MatrixXi::Zero(7, 7);
I = MatrixXi::Identity(dim_u, dim_u);
G_ << I, P; **<----- here**
// cout << G_ << endl << endl;
x = u_ * G_;
for (int i = 0; i < dim_mat_col; i++)
{
x(i) = x(i) % 2;
}
// std::cout << "correct codeword: " << x << std::endl;
// mapping for BPSK
for (int i = 0; i < dim_mat_col; i++)
{
if (x(i) == 0)
x(i) = 1;
else
x(i) = -1;
}
// awgn::awgn channel(dim_mat_col);
// channel.addGausian(this->x);
}
P is being passed by non-const reference, which means it may be modified by the functions you call. Passing a copy of P in each iteration makes sure that the modifications to P stay local to that iteration:
for (int i = 0; i < N; i++) {
MatrixXi P_copy = P;
...
}
does any one has a simple C++ code example of using MKL sparse matrix vector multiply routine? I need to use "mkl_zcsrsymv" to multiply a complex symmetric matrix (stored in lower triangular) with a complex vector, but I couldn't find a single demonstrative example on this. Unable to compile my code for complex case.
Read the documentation for mkl_zcsrsymv on Intel's homepage. Here symmetric is to be taken literally! (It does not mean Hermitian)
Compile with icpc -mkl test.c for maximal convenience.
#include <stdio.h>
#include "mkl_spblas.h"
int main()
{
/* Matrix in CRS format
*
* { { 0, 0, i }
* { 0, -1, 2 }
* { i, 2, 0 } }
*/
int m = 3;
MKL_Complex16 a[] = { {0,1}, {-1,0}, {2,0}, {0,1}, {2,0} };
int ia[] = { 0, 1, 3, 5 };
int ja[] = { 2, 1, 2, 0, 1 };
MKL_Complex16 x[] = { {1,0}, {2,0}, {3,0} };
MKL_Complex16 y[] = { {0,0}, {0,0}, {0,0} };
char uplo = 'L';
// Use MKL to compute
// y = A*x
mkl_cspblas_zcsrsymv(&uplo, &m, a, ia, ja, x, y);
printf("y = { (%g,%g), (%g,%g), (%g,%g) }\n",
y[0].real, y[0].imag,
y[1].real, y[1].imag,
y[2].real, y[2].imag
);
}
Output is y = { (0,3), (4,0), (4,1) }. Check it on WolframAlpha.
Here is also an example for mkl_dcsrmv.
#include <stdio.h>
#include "mkl_spblas.h"
int main()
{
/* Matrix in CRS format
*
* { { 0, 0, 1 }
* { 0, -1, 2 }
* { 1, 0, 0 } }
*/
int m = 3;
int k = 3;
double val[] = { 1, -1, 2, 1 };
int indx[] = { 2, 1, 2, 0 };
int pntrb[] = { 0, 1, 3 };
int pntre[] = { 1, 3, 4 };
double x[] = { 1, 2, 3 };
double y[] = { 0, 0, 0 };
double alpha = 1;
double beta = 0;
char transa = 'N';
char matdescra[] = {
'G', // type of matrix
' ', // triangular indicator (ignored in multiplication)
' ', // diagonal indicator (ignored in multiplication)
'C' // type of indexing
};
// Use MKL to compute
// y = alpha*A*x + beta*y
mkl_dcsrmv(&transa, &m, &k, &alpha, matdescra, val, indx, pntrb, pntre, x, &beta, y);
printf("y = { %g, %g, %g }\n", y[0], y[1], y[2]);
}
Output is y = { 3, 4, 1 }. Check it on WolframAlpha.
While playing with this I found out that this is directly compatible with Armadillo. This makes it very convenient to use in C++. Here I first generate a random symmetric matrix with Armadillo and convert it to sparse. This I multiply with a random vector. Finally I compare the result to Armadillo's sparse matrix-vector product. The precision differs quite substantially.
#include <iostream>
#include <armadillo>
#define MKL_Complex16 arma::cx_double
#include "mkl_spblas.h"
int main()
{
/* Matrix in CRS format
*
* { { 0, 0, i }
* { 0, -1, 2 }
* { i, 2, 0 } }
*/
int dim = 1000;
arma::sp_cx_mat a(arma::randu<arma::cx_mat>(dim,dim));
a += a.st();
arma::cx_vec x = arma::randu<arma::cx_vec>(dim);
arma::cx_vec y(dim);
char uplo = 'L';
// Use MKL to compute
// y = A*x
mkl_cspblas_zcsrsymv(&uplo, &dim,
a.values, (int*)a.col_ptrs, (int*)a.row_indices,
x.memptr(), y.memptr());
std::cout << std::boolalpha
<< arma::approx_equal(y, a*x, "absdiff", 1e-10)
<< '\n';
}
I'm trying to program a simple animation using GLUT and OpenGL in c++. I've created three functions for this purpose: catSpline(), fillArray(), and fixedAngle(). catSpline() returns a GLfloat value, fillArray() is a void function that consists of a series of loops that fills a series of arrays with GLfloat values produced using catSpline, and fixedAngle() will return a 16-unit array. Here is the code for these three methods:
GLfloat * fixedAngle(GLfloat initialX, GLfloat initialY, GLfloat initialZ, GLfloat rotX, GLfloat rotY, GLfloat rotZ)
{
ArrayXXf z(4,4); //initializing the 4x4 rotation matrixes
ArrayXXf y(4,4);
ArrayXXf x(4,4);
x<<1, 0, 0, 0,
0, cos(rotX), -sin(rotX), 0,
0, sin(rotX), cos(rotX), 0,
0, 0, 0, 1;
y<<cos(rotY), 0, sin(rotY), 0,
0, 1, 0, 0,
-sin(rotY), 0, cos(rotY), 0,
0, 0, 0, 1;
z<< cos(rotZ), -sin(rotZ), 0, 0,
sin(rotZ), cos(rotZ), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1;
ArrayXXf fin(4,4);
fin = x * y * z;
fin(0,3) = initialX;
fin(1,3) = initialY;
fin(2,3) = initialZ;
//now we've moved the translational information into the final matrix
// std::cout << fin;
fin(3,3) = 1;
GLfloat * arr;
arr = (GLfloat *) malloc(16*sizeof(GLfloat));
arr[0] = fin(0,0);
arr[1] = fin(0,1);
arr[2] = fin(0,2);
arr[3] = fin(0,3);
arr[4] = fin(1,0);
arr[5] = fin(1,1);
arr[6] = fin(1,2);
arr[7] = fin(1,3);
arr[8] = fin(2,0);
arr[9] = fin(2,1);
arr[10] = fin(2,2);
arr[11] = fin(2,3);
arr[12] = fin(3,0);
arr[13] = fin(3,1);
arr[14] = fin(3,2);
arr[15] = fin(3,3);
return arr;
}
GLfloat catSpline(GLfloat x1, GLfloat x2, GLfloat x3, GLfloat x4, GLfloat t)
{
ArrayXXf M(4,4); //4x4 M matrix
ArrayXXf P(4,1); //matrix to hold keyframe x values
P(0,0) = x1;
P(1,0) = x2;
P(2,0) = x3;
P(3,0) = x4;
//keyframe x values
M(0,0) = -0.5;
M(0,1) = 2-(-0.5);
M(0,2) = -0.5-2;
M(0,3) = 0.5;
M(1,0) = 2*0.5;
M(1,1) = 0.5-3;
M(1,2) = 3-(2*0.5);
M(1,3) = -0.5;
M(2,0) = -0.5;
M(2,1) = 0;
M(2,2) = 0.5;
M(2,3) = 0;
M(3,0) = 0;
M(3,1) = 1;
M(3,2)=0;
M(3,3)=0;
ArrayXXf T(1,4);
T(0,0) = t*t*t; //you can't cube a float, but you can get the same result by doing this
T(0,1) = t*t;
T(0,2) = t;
T(0,3)=1;
//now the T matrix is filled
ArrayXXf TM(1,4);
TM(0,0) = (T(0,0) * M(0,0)) + (T(0,1) * M(1,0)) + (T(0,2) * M(2,0)) + (T(0,3) * M(0,3));
TM(0,1) = (T(0,0) * M(0,1)) + (T(0,1) * M(1,1)) + (T(0,2) * M(2,1)) + (T(0,3) * M(3,1));
TM(0,2) = (T(0,0) * M(0,2)) + (T(0,1) * M(1,2)) + (T(0,2) * M(2,2)) + (T(0,3) * M(3,2));
TM(0,3) = (T(0,0) * M(0,3)) + (T(0,1) * M(1,3)) + (T(0,2) * M(2,3)) + (T(0,3) * M(3,3));
//first multiply T amd M
GLfloat TMP;
TMP = (TM(0,0) * P(0,0)) + (TM(0,1) *P(1,0)) + (TM(0,2) * P(2,0)) + (TM(0,3) * P(3,0));
return TMP;
}
void fillArrays()
{
/* zRot = catSpline(2, 4, 5, 6);
yRot = catSpline(1, 4, 6, 7);
xRot = catSpline(6, 3, 2, 6);
xArr = catSpline(9, 4, 3, 10);
yArr = catSpline(1, 2, 4, 8);
zArr = catSpline(8, 3, 1, 3);*/
for(int j=0; j>=100; j++)
{
xArr[j] = catSpline(2, 4, 5, 6, t);
t+=0.1;
}
for(int i=0; i>=100; i++)
{
yArr[i] = catSpline(2, 4, 5, 6, ty);
ty+=0.1;
}
for(int k=0; k>=100; k++)
{
xArr[k] = catSpline(2, 4, 5, 6, tz);
tz += 0.1;
}
for(int a=0; a>=100; a++)
{
xRot[a] = catSpline(2, 4, 5, 6, rx);
rx += 0.1;
}
for(int b=0; b>=100; b++)
{
yRot[b] = catSpline(2, 4, 5, 6, ry);
rz += 0.1;
}
for(int c=0; c>=100; c++)
{
zRot[c] = catSpline(2, 4, 5, 6, rz);
rz += 0.1;
}
}
The way I use these three functions is in a loop called Render, I set up OpenGL for displaying an animation of a teapot model, call fillArrays(), and then attempt to store the result of a single fixedAngle call (using a few entries form the arrays filled in just before) in a new array called foo. This seems to be the cause of the errors, with foo only containing a pointer address rather than pointing to the actual array so I can use it. This is the code I'm using to call these functions:
fillArrays();
GLfloat * foo;
foo = (GLfloat *) malloc(16*sizeof(GLfloat));
foo = fixedAngle(xArr[tp], yArr[tp], zArr[tp], xRot[tp], yRot[tp], zRot[tp]);
glLoadMatrixf(foo);
After having used multiple print statements to print out the results of my functions, I know that the problem has to be how I set up the pointers somewhere. Can anyone help me return the array correctly?
Please note: if some of the matrix syntax seems unfammiliar, it's because I'm using a c++ library called Eigen to do some of the matrix math. Once again, after having rigorously printed out the results of the functions, I know that the functions that use Eigen syntax are producing the right values.
You can replace...
GLfloat * arr;
arr = (GLfloat *) malloc(16*sizeof(GLfloat));
...with...
std::vector<GLfloat> arr(16);
...or even directly initialise it instead of copying elements afterwards...
std::vector<GLfloat> arr { fin(0,0), fin(0,1), fin(0,2), fin(0,3),
fin(1,0), fin(1,1), fin(1,2), fin(1,3),
fin(2,0), fin(2,1), fin(2,2), fin(2,3),
fin(3,0), fin(3,1), fin(3,2), fin(3,3) };
...which - FWIW - could also be done like this...
std::vector<GLfloat> arr;
for (int a = 0; a <= 3; ++a)
for (int b = 0; b <= 3; ++b)
arr.push_back(fin(a,b));
With any of the above, you'll need to change the return type correspondingly...
std::vector<GLfloat> fixedAngle(
GLfloat initialX, GLfloat initialY, GLfloat initialZ,
GLfloat rotX, GLfloat rotY, GLfloat rotZ)
{
...
...then you can call fixedAngle and use foo like this:
fillArrays();
std::vector<GLfloat> foo = fixedAngle(xArr[tp], yArr[tp], zArr[tp],
xRot[tp], yRot[tp], zRot[tp]);
glLoadMatrixf(foo.data()); // or `&foo[0]` if you prefer...
I'm trying to understand the game algorithm called "Boggle"
which finds words in an N*N matrix.
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 6; // max length of a word in the board
char in[N * N + 1]; // max length of a word
char board[N+1][N+2]; // keep room for a newline and null char at the end
char prev[N * N + 1];
bool dp[N * N + 1][N][N];
// direction X-Y delta pairs for adjacent cells
int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
bool visited[N][N];
bool checkBoard(char* word, int curIndex, int r, int c, int wordLen)
{
if (curIndex == wordLen - 1)
{
//cout << "Returned TRUE!!" << endl;
return true;
}
int ret = false;
for (int i = 0; i < 8; ++i)
{
int newR = r + dx[i];
int newC = c + dy[i];
if (newR >= 0 && newR < N && newC >= 0 && newC < N && !visited[newR] [newC] && word[curIndex+1] == board[newR][newC])
I do not understand this part:
// direction X-Y delta pairs for adjacent cells
int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
Why do these array have the values they have and why does this work?
These arrays represent the possible combinations of row and column offsets from the current "cursor" location (which is an x,y coordinate tracked in the code as variables c,r):
// direction X-Y delta pairs for adjacent cells
int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
For example, if you imagine a 3x3 square grid, and consider the central box to be the current location, then the other 8 surrounding cells are those indicated by these sets of row and column offsets. If we took the offsets at index 2 (dx[2] = 1 and dy[2] = 0), this would indicate the cell one row down (and zero shifting left/right).
I am using this website on how to compute a hermite curve under the heading The Math in Matrix Form to make a hermite curve.
Here is my code so far...
// calculate hermite curve
GLfloat S[4][1];
GLfloat C[4][3] = {{height, 0, 0},
{0, radius, 0},
{0, 2 * radius, 0},
{-2 * height, 0, 0}};
GLfloat h[4][4] = {{ 2,-2, 1, 1},
{-3, 3,-2,-1},
{ 0, 0, 1, 0},
{ 1, 0, 0, 0}};
unsigned int rows;
unsigned int cols;
float val;
for (int x = 0; x < l_vertices; x++) {
float segment = (float)x / l_vertices;
S[0][0] = pow(segment, 3);
S[1][0] = pow(segment, 2);
S[2][0] = pow(segment, 1);
S[3][0] = 1;
GLfloat midwayArray[4][4] = {{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0}};
GLfloat finalArray[4][1] = { 0, 0, 0, 0};
rows = 4;
cols = 4;
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
for (unsigned int k = 0; k < 1; k++) {
val = S[i][k] * h[k][j];
midwayArray[i][j] += val;
}
}
}
rows = 4;
cols = 1;
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
for (unsigned int k = 0; k < 4; k++) {
val = midwayArray[i][k] * C[k][j];
finalArray[i][j] += val;
}
}
}
profileCurve[0][x] = finalArray[0][0];
profileCurve[1][x] = finalArray[1][0];
profileCurve[2][x] = finalArray[2][0];
}
But I am getting mainly zeros for some reason. I think my matrix multiplication is not being done correctly.
Also, just some information on how my code currently works. The first inner nested for loop is multiplying S and h just like the website says. Then the second inner nested for loop is multiplying the result of the previous matrix multiplication with C just like the website says.
I think assign the result coordinates of the final array for that iteration of x to my profileCurve array which is going to store all the coordinates that make up the hermite curve.