getting input parameters from matlab using C++ mex Function - c++

double learning_rate = 1;
int training_epochs = 1;
int k = 1;
int train_S = 6;
int test_S = 6;
int visible_E = 6;
int hidden_E = 6;
// training data
int train_X[6][6] = {
{1, 1, 1, 0, 0, 0},
{1, 0, 1, 0, 0, 0},
{1, 1, 1, 0, 0, 0},
{0, 0, 1, 1, 1, 0},
{0, 0, 1, 1, 1, 0},
{0, 0, 1, 1, 1, 0}
};
the above code are the input parameters am giving to my function. but i would like to cast them into a function withing my mexFunction and simply call them.
the matlab side has the following
clear *
close all
clc
%% Load the data
X= [ 1, 1, 1, 0, 0, 0; ...
1, 0, 1, 0, 0, 0; ...
1, 1, 1, 0, 0, 0; ...
0, 0, 1, 1, 1, 0; ...
0, 0, 1, 1, 1, 0; ...
0, 0, 1, 1, 1, 0];
%% Define Parameters
numHiddenUnits = 6;
numIterations = 1000;
kCD = 1;
%% Compute the RBM
x = RBM(X, numHiddenUnits, numIterations, kCD);

Scalar input parameters are fairly simple. Matrix inputs are little trickier because they use old-school Fortran column major order, you may need to transpose the data before you send it to your function. Here's kind of an example, you'll have to fill in the blanks:
/*=========================================================
* Built on:
* matrixDivide.c - Example for illustrating how to use
* LAPACK within a C MEX-file.
*
* This is a MEX-file for MATLAB.
* Copyright 2009 The MathWorks, Inc.
*=======================================================*/
/* $Revision: 1.1.6.2 $ $Date: 2009/05/18 19:50:18 $ */
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double * pX, * pNumHiddenUnits, * pNumIter, * pkCD; /* pointers to inputs */
double * pOutput; /* output arugments */
mwSignedIndex m,n; /* matrix dimensions */
int i, j;
/* Check for proper number of arguments. */
if ( nrhs != 4)
{
mexErrMsgIdAndTxt("MATLAB:RBM:rhs",
"This function requires 4 inputs.");
}
pX = mxGetPr(prhs[0]); /* pointer to first input, X matrix */
pNumHiddenUnits = mxGetPr(prhs[1]); /* pointer to second input, scalar hidden units */
pNumIter = mxGetPr(prhs[2]); /* pointer to third input, scalar number of iterations */
pkCD = mxGetPr(prhs[3]); /* pointer to third input, scalar kCD */
/* dimensions of input matrix */
m = (mwSignedIndex)mxGetM(prhs[0]);
n = (mwSignedIndex)mxGetN(prhs[0]);
/* Validate input arguments */
if (m < 1 && n < 1)
{
mexErrMsgIdAndTxt("MATLAB:RBM:notamatrix",
"X must be a matrix.");
}
plhs[0] = mxCreateDoubleMatrix(m, n, mxREAL);
pOutput = mxGetPr(plhs[0]);
for (i = 0; i < n; ++i)
{
for (j = 0; j < m; ++j)
{
int index = j * n + i;
pOutput[index] = pX[i * m + j];
}
}
}
/* */

Related

Create multiple objects for a simulation

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;
...
}

using MKL sparse matrix vector multiply

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';
}

Problems calling a function that returns an array

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...

Meaning of "direction X-Y delta pairs for adjacent cells"

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).

Implementing a hermite curve

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.