Complex Matrix Inversion with GSL - c

I am in the middle of porting prototype matlab code into C, and have hit a hitch on inverting a nxn matrix of complex numbers.
I am using GSL to perform LU decompositon and inversion with the following code:
size_t matSize = 4;
gsl_permutation *perm = gsl_permutation_calloc(matSize);
gsl_matrix_complex *mat = gsl_matrix_complex_calloc(matSize, matSize);
gsl_matrix_complex *inv = gsl_matrix_complex_calloc(matSize, matSize);
gsl_complex temp;
for(int i = 0; i < matSize; i++) {
for(int j = 0;j < matSize; j++) {
GSL_SET_COMPLEX(&temp,i+1,j+1);
gsl_matrix_complex_set(mat,i,j,temp);
}
}
int s;
gsl_linalg_complex_LU_decomp(mat, perm, &s);
gsl_linalg_complex_LU_invert(mat, perm, inv);
for(int i = 0; i < matSize; i++) {
for(int j = 0; j < matSize; j++) {
printf("%f + %fi \n",GSL_REAL(gsl_matrix_complex_get(inv, i, j)),GSL_IMAG(gsl_matrix_complex_get(inv, i, j)));
}
}
However comparing the results I get to matlab, they are not similar at all. I know matlab does not always use LU for inversion as it has an algorithm decision tree depending on matrix properties, but I would expect comparable results.
Any help welcomed. As well as recommendations for other libraries / techniques of inversion (not that GSL is wrong, without a doubt I am!) the matrix I have is type fftw_complex and I would rather avoid converting too/from gsl_complex_matrix.

Related

Implementing LU factorization with partial pivoting in C using only one matrix

I have designed the following C function in order to compute the PA = LU factorization, using only one matrix to store and compute the data:
double plupmc(int n, double **c, int *p, double tol) {
int i, j, k, pivot_ind = 0, temp_ind;
int ii, jj;
double pivot, *temp_row;
for (j = 0; j < n-1; ++j) {
pivot = 0.;
for (i = j; i < n; ++i)
if (fabs(c[i][j]) > fabs(pivot)) {
pivot = c[i][j];
pivot_ind = i;
}
temp_row = c[j];
c[j] = c[pivot_ind];
c[pivot_ind] = temp_row;
temp_ind = p[j];
p[j] = p[pivot_ind];
p[pivot_ind] = temp_ind;
for (k = j+1; k < n; ++k) {
c[k][j] /= c[j][j];
c[k][k] -= c[k][j]*c[j][k];
}
}
return 0.;
}
where n is the order of the matrix, c is a pointer to the matrix and p is a pointer to a vector storing the permutations done when partial pivoting the system. The variable tol is not relevant for now. The program works storing in c both the lower and upper triangular parts of the factorization, where U corresponds to the upper triangular part of c and L corresponds to the strictly lower triangular part of c, adding 1's in the diagonal. For what I have been able to test, the part of the program corresponding to partial pivoting is working properly, however, the algorithm used to compute the entries of the matrix is not giving the expected results, and I cannot see why. For instance, if I try to compute the LU factorization of the matrix
1. 2. 3.
4. 5. 6.
7. 8. 9.
I get
1. 0. 0. 7. 8. 9.
l : 0.143 1. 0. u : 0. 2. 1.714*
0.571 0.214* 1. 0. 0. 5.663*
the product of which does not correspond to any permutation of the matrix c. In fact, the wrong entries seem to be the ones marked with a star.
I would appreciate any suggestion to fix this problem.
I found the problem with your code, there was a little conceptual error in the way that you were normalizing the row while computing the actual decomposition:
for (k = j+1; k < n; ++k) {
c[k][j] /= c[j][j];
c[k][k] -= c[k][j]*c[j][k];
}
became:
for (k = j+1; k < n; ++k) {
temp=c[k][j]/=c[j][j];
for(int q=j+1;q<n;q++){
c[k][q] -= temp*c[j][q];
}
}
which returns the result:
7.000000 8.000000 9.000000
0.142857 0.857143 1.714286
0.571429 0.500000 -0.000000
If you have any questions I am happy to help.
Full implementation here:
#include<stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
double plupmc(int n, double **c, int *p, double tol) {
int i, j, k, pivot_ind = 0, temp_ind;
int ii, jj;
double *vv=calloc(n,sizeof(double));
double pivot, *temp_row;
double temp;
for (j = 0; j < n; ++j) {
pivot = 0;
for (i = j; i < n; ++i)
if (fabs(c[i][j]) > fabs(pivot)) {
pivot = c[i][j];
pivot_ind = i;
}
temp_row = c[j];
c[j] = c[pivot_ind];
c[pivot_ind] = temp_row;
temp_ind = p[j];
p[j] = p[pivot_ind];
p[pivot_ind] = temp_ind;
for (k = j+1; k < n; ++k) {
temp=c[k][j]/=c[j][j];
for(int q=j+1;q<n;q++){
c[k][q] -= temp*c[j][q];
}
}
for(int q=0;q<n;q++){
for(int l=0;l<n;l++){
printf("%lf ",c[q][l]);
}
printf("\n");
}
}
return 0.;
}
int main() {
double **x;
x=calloc(3,sizeof(double));
for(int i=0;i<3;i++){
x[i]=calloc(3,sizeof(double));
}
memcpy(x[0],(double[]){1,2,3},3*sizeof(double));
memcpy(x[1],(double[]){4,5,6},3*sizeof(double));
memcpy(x[2],(double[]){7,8,9},3*sizeof(double));
int *p=calloc(3,sizeof(int));
memcpy(p,(int[]){0,1,2},3*sizeof(int));
plupmc(3,x,p,1);
for(int i=0;i<3;i++){
free(x[i]);
}
free(p);
free(x);
}

C programming: Finding the confusion matrix given the truth vector and prediction

Assume that we have given two vector of labels which one of them is the truth and the other one is the predicted ones. My question is how we can write a correct confusion matrix for it in C. This is a function which supposes to find the confusion matrix in a larger c code. I appreciate some help regarding this.
double ConfusionMatrix(int truth[], int prediction[]){
/* The truth vector of labels, the predicted vector of labels, and the unique length of labels which should be given. */
int i, j, c;
int labels; /* The length of unique labels */
conf_mat = (float**)calloc(truth, sizeof(float*)); /* Allocating Memory to the Confusion Matrix. */
for (i = 0; i < truth; i++)
conf_mat[i] = (float*)calloc(truth, sizeof(float));
for (i = 0; i < truth; i++)
for (c = 0; c < truth; c++)
conf_mat[c][i] = 0.0;
for (j = 0; j < truth; j++){
c = labels[j];
for (i = 0; i < prediction; i++)
conf_mat[c][i] += prediction[i][j];
}
/* As Confusion Matrix is sparse, then print only the entries above the threshold. */
printf("Print the Confusion Matrix \n Print only the entries above 0.1\n");
for (c = 0; c < truth; c++){
printf("\n\nClass %d documents were classified in these classes\n", c);
for (i = 0; i < truth; i++)
if (conf_mat[c][i] >= 0.1)
printf("class %d:%5.1f times ", i, conf_mat[c][i]);
}
}

Cumulative sum in C is blowing up to infinity

I'm generally an R user but I am trying to use to C for some lower level cumulative sums and multiplications.
I am trying to generate a cumulative sum of eta and storing the result in tmp0. However, when I output tmp0 it either gives me Inf, NaN, or some arbitrarily large number. I double checked the same cumulative sum in R and it works fine; I am not sure why C is not handling it. Below is the code that I am using:
int i,j;
const int p = ncov, n = nin;
double accNum0[n]; //accumulate first part of likelihood sum eta_i
double accNum1[n]; //accumulate the backwards numerator
double accNum2[n]; //acumulate the forward numerator (weighted)
double tmp0 = 0;
double eta[n]; //calculate linear predictor in this step (X %*% beta)
for(i = 0; i < n; i++) {
for (j = 0; j < p; j++)
eta[i] += b[j] * x[n * j + i];
}
for (i = 0; i < n; ++i) {
tmp0 += eta[i];
}
return (tmp0);
Again, I am fairly new to C so I may be making some rookie mistakes and would greatly appreciate any (and all) suggestions!
There might be errors with how you are initializing b or x. However, one definite error is that eta is being used uninitialized. This means eta[i] may begin with some arbitrary value instead of 0 as you are likely expecting.
Add an initialization before accumulating into it.
for(i = 0; i < n; i++) {
eta[i] = 0;
for (j = 0; j < p; j++)
eta[i] += b[j] * x[n * j + i];
}

Optimising divide operation inside Jacobi relaxation

I am trying to optimise the divide operation from the Jacobi relaxation formula.
Also doing profiling using perf.
Here is my code
for (int l = 0; l < iter; l++) {
for (i = 1; i < height; i++) {
for (j = 1; j < width; j++) {
for (k = 1; k < length; k++) {
float val = 0.0f;
// Do the Jacobi additions here
// From profiling, fastest is to fetch k+/-1,j,i
// Slowest is to fetch k,j,i+/-1
// Scale with dimensions of the array
val -= dim * array[k][j][i];
// Want to optimise this
val /= 6.0; // profiling shows this as the slowest op
// Some code here to put the result into the output array
}
}
}
}
The size of the 3D array can be from 100x100x100 up to 1000x1000x1000.
I've tried to multiply it to 1.0f/6.0f but this does not seem to make a difference. The array is a 3D array of floats.

Multiplying two arrays in C

I'm trying to multiply two multidimensional arrays to form a matrix. I have this function. This should work in theory. However, I am just getting 0s and large/awkward numbers. Can someone help me with this?
int **matrix_mult( int **a, int **b, int nr1, int nc1, int nc2 )
{
int **c;
int i,j,k,l;
c = malloc(sizeof(int *)*nr1);
if (c == NULL){
printf("Insuff memm");
}
for(l=0;l<nr1;l++){
c[l] = malloc(sizeof(int)*nc1);
if (c[l] == NULL){
printf("Insuff memm");
}
}//for loop
for (i=0;i<nr1;i++){
for (j=0;j<nc2;j++){
for (k=0;k<nc1;k++){
c[i][j] = (a[i][k]) * (b[k][j]);
}
}
}
return( c );
}
Are you doing mathematical matrix multiplication? If so shouldn't it be:
for(i = 0; i < nr1; i++)
{
for(j = 0; j < nc1; j++)
{
c[i][k] = 0;
for(k = 0; k < nc2; k++)
{
c[i][k] += (a[i][j]) * (b[j][k]);
}
}
}
My full and final solution, tested to produce sensible results (I didn't actually do all the calculations myself manually to check them) and without any sensible niceties such as checking memory allocations work, is:
int **matrix_mult(int **a, int **b, int nr1, int nc1, int nc2)
{
int **c;
int i, j, k;
c = malloc(sizeof(int *) * nr1);
for (i = 0; i < nr1; i++)
{
c[i] = malloc(sizeof(int) * nc2);
for (k = 0; k < nc2; k++)
{
c[i][k] = 0;
for (j = 0; j < nc1; j++)
{
c[i][k] += (a[i][j]) * (b[j][k]);
}
}
}
return c;
}
There were a few typos in the core of the for loop in my original answer, mostly due to my being mislead by a different answer. These have been corrected for posterity.
If you change c[i][j] = (a[i][k]) * (b[k][j]); to c[i][j] += (a[i][k]) * (b[k][j]); in your code then it will work just fine provided that
nr1 is number of rows of matrix a
nc1 is the number of columns of the matrix a
nc2 is the number of columns of the matrix b
Just be sure that the matrix c is initiated with zeroes. You can just use calloc instead of malloc when allocating space, or memset the allocated array after a call to malloc.
One more tip is to avoid using the letter l when accessing array elements. when tired, you will have hard time noticing errors with l vs 1.

Resources