How can i create proportionnel matrix from an existing matrix - c

Starting matrix:
tab[2][3]
Values:
1 0 1
0 1 0
I want to create this matrix (rows and cols are proportionnel to our tab[2][3] by x50):
tab[100][150]
Values:
for row 0 to 50:
col 0 to 50 = 1
col 51 to 100 = 0
col 101 to 150 = 1
for row 51 to 100
col 0 to 50 = 0
col 51 to 100 = 1
col 101 to 150 = 0
I need help for creating this matrix in c
Thank you

I feel cheap answering this trivial question with a trivial bit of code(but since 101010 is binary for 42, a tribute to Douglas Adams is not to be ignored.)
int main() {
int base[2][3] = { { 1, 0, 1, }, { 0, 1, 0 } };
int big[2*50][3*50};
for( int r = 0; r < 2 * 50; r++ )
for( int c = 0; c < 3 * 50; c++ )
big[r][c] = base[r/50][c/50];
return 0;
}
Generalising this (and improving it) is left as an exercise for the reader.
(Here is another recent answer (today) involving DNA (Douglas Noel Adams)
https://stackoverflow.com/a/74765117/17592432
Merry Christmas!)

Related

how to calculate covariance matrix of 2d array in C using GSL library

I have 2D array :
21 6 160 110 3.90 2.62 16.46 0 1 4 4
21 6 160 110 3.9 2.875 17.02 0 1 4 4
22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
18.7 8 360 175 3.15 3.44 17.02 0 0 3 2
18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
14.3 8 360 245 3.21 3.570 15.84 0 0 3 4
24.4 4 146.7 62 3.69 3.190 20 1 0 4 2
22.8 4 140.8 95 3.92 3.15 22.90 1 0 4 2
19.2 6 167.6 123 3,92 3.440 18.3 1 0 4 4
And I want to calculate the covariance-variance matrix in C language using GSL library. Can anyone guide me on how to use this library?
I am assuming that you have a 2D array with 55 rows and 2 columns (as you have mentioned 110 values value of data above). First, you have to put this data in a file, say test.dat, (download from here) then you can read it in a gsl_matrix and calculate the covariance matrix using the gsl_stats_covariance function as follows:
#include <stdio.h>
#include <gsl/gsl_statistics.h>
#include <gsl/gsl_matrix.h>
int main (void)
{
int i, j;
int rows = 55, col = 2;
gsl_matrix * m = gsl_matrix_alloc (rows, col);
gsl_matrix * C = gsl_matrix_alloc (col, col);
{
FILE * f = fopen ("test.dat", "rb");
gsl_matrix_fscanf (f, m);
fclose (f);
}
for (i = 0; i < m->size2; i++)
{
for (j = 0; j < m->size2; j++)
{
gsl_vector_view col1, col2;
col1 = gsl_matrix_column (m, i);
col2 = gsl_matrix_column (m, j);
double cov = gsl_stats_covariance(col1.vector.data, col1.vector.stride,
col2.vector.data, col2.vector.stride,
col1.vector.size);
gsl_matrix_set (C, i, j, cov);
}
}
for (i = 0; i < C->size1; i++)
{
for (j = 0; j < C->size2; j++)
{
printf("%f ", gsl_matrix_get(C, i, j));
}
}
gsl_matrix_free (m);
gsl_matrix_free (C);
return 0;
}
You can see that the C matrix has been initialized as a 2x2 matrix because the covariance matrix is a square matrix. Each column of the matrix m is sliced as gsl_vector_view and utilized in the gsl_stats_covariance function. In the end, the covariance matrix is printed.

Represent a tridiagonal sparse matrix in column major order

Main Question:-
If the elements in the band formed by the three diagonals of a tridiagonal matrix X are represented column-wise in an array Y, with X[1,1] being stored in Y[1], then write an algorithm to determine the value of X[i, j], 1 <= i, j <= n from array Y.
I did some calculation in rough and found the size of 1D array required and index to row and column index for main diagonal and upper diagonal but failing to do so for lower diagonal
CONSIDERING A MATRIX WITH 5 ROWS AND 5 COLUMNS
|A11 A12 0 0 0 |
|A21 A22 A23 0 0 |
| 0 A32 A33 A34 0 |
| 0 0 A43 A44 A45|
| 0 0 0 A54 A55|
Size of the array (3*n - 2),
here size of the array = (3*5 - 2) = 13
0 1 2 3 4 5 6 7 8 9 10 11 12
A11 A21 A12 A22 A32 A23 A33 A43 A34 A44 A54 A45 A55
i=row index, 1<=i<=N
j=column index, 1<=j<=N
k=array index
Now for main diagonal
i j k
1 1 0
2 2 3
3 3 6
4 4 9
5 5 12
I got the relation as 3i - 3
For Upper diagonal
i j k
1 2 2
2 3 5
3 4 8
4 5 11
I got the relation as 4i - j
Now for lower diagonal(question)
i j k
2 1 1
3 2 4
4 3 7
5 4 10
Relation ??
Summary
You'll find that (indexing from 1), for an NxN tridiagonal matrix X
linearized in column-major order into an array Z, the entry in row r:
On the main diagonal of X is at index (3 * c - 2) of Y for c = 1..N;
On the upper-diagonal of X is at (3 * c - 3) of Y (for c = 1..N-1);
On the lower-diagonal of X is at (3 * c - 1) of Y (for c = 2..N).
For an element with row r, column c (both in the range 1..N):
if |r - c| > 1 then the value is zero;
if c == r then it is on the leading diagonal;
if c = r + 1 then it is on the upper diagonal;
if c = r - 1 then it is on the lower diagonal.
Of course, in C, arrays are indexed from zero, not one.
Cogitations
NxN tri-diagonal matrix X
Linearized in row-major order into array Y with 3*N-2 entries
Linearized in column-major order into array Z with 3*N-2 entries
Non-zero elements have c = r + { -1, 0, +1 }
Equivalently they have r = c + { -1, 0, +1 }
With one-based indexing, the first row with an element on the lower
diagonal is r = 2 and the last row with an element on the upper
diagonal is r = N - 1.
With zero-based indexing, the first row with an element on the lower
diagonal is r = 1 and the last rows with an element on the upper
diagonal is r = N - 2.
In the linearized vectors, the notation is:
D = diagonal, L = lower diagonal, U = upper diagonal
Row-Major Order with Zero-Based Indexing
X c = 0 1 2 3 4 5
+----------------------
r = 0 | 1 2 0 0 0 0
r = 1 | 3 4 5 0 0 0
r = 2 | 0 6 7 8 0 0
r = 3 | 0 0 9 10 11 0
r = 4 | 0 0 0 12 13 14
r = 5 | 0 0 0 0 15 16
D U L D U L D U L D U L D U L D
Y = { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 }
Index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Elements on main diagonal at indexes: 0, 3, 6, 9, 12, 15
Elements on upper diagonal at indexes: 1, 4, 7, 10, 13
Elements on lower diagonal at indexes: 2, 5, 8, 11, 14
Function get_rm_0():
X[r,c] = 0 if |r - c| > 1
X[r,c] = 3 * r + 0 if r == c + 0 — Main diagonal
X[r,c] = 3 * r + 1 if r == c - 1 — Upper diagonal
X[r,c] = 3 * r - 1 if r == c + 1 — Lower diagonal
Always subject to 0 <= r < N; 0 <= c < N
Row-Major Order with One-Based Indexing
X c = 1 2 3 4 5 6
+----------------------
r = 1 | 1 2 0 0 0 0
r = 2 | 3 4 5 0 0 0
r = 3 | 0 6 7 8 0 0
r = 4 | 0 0 9 10 11 0
r = 5 | 0 0 0 12 13 14
r = 6 | 0 0 0 0 15 16
D U L D U L D U L D U L D U L D
Y = { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 }
Index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Elements on main diagonal at indexes: 1, 4, 7, 10, 13, 16
Elements on upper diagonal at indexes: 2, 5, 8, 11, 14
Elements on lower diagonal at indexes: 3, 6, 9, 12, 15
Function get_rm_1():
X[r,c] = 0 if |r - c| > 1
X[r,c] = 3 * r - 2 if r == c + 0 — Main diagonal
X[r,c] = 3 * r - 1 if r == c - 1 — Upper diagonal
X[r,c] = 3 * r - 3 if r == c + 1 — Lower diagonal
Always subject to 0 < r <= N; 0 <= c <= N
Column-major instead of row-major order
You are correct. Here you are considering row-major order. I
wanted to store the elements in the array as:
Z = { 1, 3, 2, 4, 6, 5, 7, 9, 8, 10, 12, 11, 13, 15, 14, 16 }
as per your example
Column-Major Order with One-Based Indexing
So, you can make a parallel argument to the one I gave. Annotate
your column-major array Z similarly to the way I annotated the
row-major array Y:
D L U D L U D L U D L U D L U D
Z = { 1, 3, 2, 4, 6, 5, 7, 9, 8, 10, 12, 11, 13, 15, 14, 16 }
Index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Elements on main diagonal at indexes: 1, 4, 7, 10, 13, 16
Elements on upper diagonal at indexes: 3, 6, 9, 12, 15
Elements on lower diagonal at indexes: 2, 5, 8, 11, 14
Function get_cm_1():
X[r,c] = 0 if |c - r| > 1
X[r,c] = 3 * c - 2 if c == r + 0 — Main diagonal
X[r,c] = 3 * c - 3 if c == r + 1 — Upper diagonal
X[r,c] = 3 * c - 1 if c == r - 1 — Lower diagonal
Always subject to 0 < r <= N; 0 < c <= N.
Column-Major Order with Zero-Based Indexing
D L U D L U D L U D L U D L U D
Z = { 1, 3, 2, 4, 6, 5, 7, 9, 8, 10, 12, 11, 13, 15, 14, 16 }
Index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Elements on main diagonal at indexes: 0, 3, 6, 9, 12, 15
Elements on upper diagonal at indexes: 2, 5, 8, 11, 14
Elements on lower diagonal at indexes: 1, 4, 7, 10, 13
Function get_cm_0():
X[r,c] = 0 if |c - r| > 1
X[r,c] = 3 * c + 0 if c == r + 0 — Main diagonal
X[r,c] = 3 * c - 1 if c == r + 1 — Upper diagonal
X[r,c] = 3 * c + 1 if c == r - 1 — Lower diagonal
Always subject to 0 <= r < N; 0 <= c < N.
Code
Source file td59.c:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
enum { N = 6 };
static const int X[N][N] =
{
{ 1, 2, 0, 0, 0, 0 },
{ 3, 4, 5, 0, 0, 0 },
{ 0, 6, 7, 8, 0, 0 },
{ 0, 0, 9, 10, 11, 0 },
{ 0, 0, 0, 12, 13, 14 },
{ 0, 0, 0, 0, 15, 16 },
};
static const int Y[3*N-2] =
{
1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16,
};
static const int Z[3*N-2] =
{
1, 3, 2, 4, 6, 5, 7, 9,
8, 10, 12, 11, 13, 15, 14, 16,
};
/* rm = row major, cm = column major, 0 = zero-based, 1 = one-based */
static int get_rm_0(int r, int c)
{
assert(r >= 0 && r < N);
assert(c >= 0 && c < N);
//printf("%s(): r = %d, c = %d\n", __func__, r, c);
if (abs(r - c) > 1) /* Off tridiagonal */
return 0;
int index;
if (r == c) /* Main diagonal */
index = 3 * r + 0;
else if (r == c - 1) /* Upper diagonal */
index = 3 * r + 1;
else
{
assert(r == c + 1);
index = 3 * r - 1; /* Lower diagonal */
}
//printf("%s(): r = %d, c = %d, i = %d, v = %d\n", __func__, r, c, index, Y[index]);
return Y[index];
}
static int get_rm_1(int r, int c)
{
assert(r > 0 && r <= N);
assert(c > 0 && c <= N);
//printf("%s(): r = %d, c = %d\n", __func__, r, c);
if (abs(r - c) > 1) /* Off tridiagonal */
return 0;
int index;
if (r == c) /* Main diagonal */
index = 3 * r - 2;
else if (r == c - 1) /* Upper diagonal */
index = 3 * r - 1;
else
{
assert(r == c + 1);
index = 3 * r - 3; /* Lower diagonal */
}
//printf("%s(): r = %d, c = %d, i = %d, v = %d\n", __func__, r, c, index, Y[index-1]);
return Y[index-1];
}
static int get_cm_0(int r, int c)
{
assert(r >= 0 && r < N);
assert(c >= 0 && c < N);
//printf("%s(): r = %d, c = %d\n", __func__, r, c);
if (abs(r - c) > 1) /* Off tridiagonal */
return 0;
int index;
if (c == r) /* Main diagonal */
index = 3 * c + 0;
else if (c == r + 1) /* Upper diagonal */
index = 3 * c - 1;
else
{
assert(c == r - 1);
index = 3 * c + 1; /* Lower diagonal */
}
//printf("%s(): r = %d, c = %d, i = %d, v = %d\n", __func__, r, c, index, Z[index]);
return Z[index];
}
static int get_cm_1(int r, int c)
{
assert(r > 0 && r <= N);
assert(c > 0 && c <= N);
//printf("%s(): r = %d, c = %d\n", __func__, r, c);
if (abs(r - c) > 1) /* Off tridiagonal */
return 0;
int index;
if (c == r) /* Main diagonal */
index = 3 * c - 2;
else if (c == r + 1) /* Upper diagonal */
index = 3 * c - 3;
else
{
assert(c == r - 1);
index = 3 * c - 1; /* Lower diagonal */
}
//printf("%s(): r = %d, c = %d, i = %d, v = %d\n", __func__, r, c, index, Z[index-1]);
return Z[index-1];
}
static void dump_matrix(const char *tag, int rows, int cols,
const int matrix[rows][cols], int base)
{
printf("%s (%dx%d) %d-based:\n", tag, rows, cols, base);
printf(" c =");
for (int c = 0; c < cols; c++)
printf(" %2d", c + base);
putchar('\n');
for (int r = 0; r < rows; r++)
{
printf("r = %d: {", r + base);
for (int c = 0; c < cols; c++)
printf(" %2d", matrix[r][c]);
puts(" }");
}
putchar('\n');
}
static void dump_vector(const char *tag, int values, const int vector[values], int base)
{
printf("Vector %s (%d) %d-based:\n", tag, values, base);
int len = 0;
const char *pad = "";
for (int i = 0; i < values; i++)
{
len += printf("%s[%2d] = %2d,", pad, i + base, vector[i]);
pad = " ";
if (len > 80)
{
putchar('\n');
len = 0;
pad = "";
}
}
if (len > 0)
putchar('\n');
putchar('\n');
}
static void reconstruct_matrix(const char *matrix_tag, const char *vector_tag,
int values, const int vector[values],
int rows, int cols, int (*getter)(int r, int c), int base)
{
dump_vector(vector_tag, values, vector, base);
printf("%s (%dx%d) %d-based:\n", matrix_tag, rows, cols, base);
for (int r = 0 + base; r < rows + base; r++)
{
printf("r = %d: {", r);
for (int c = 0 + base; c < cols + base; c++)
printf(" %2d", (*getter)(r, c));
puts(" }");
}
putchar('\n');
}
int main(void)
{
dump_matrix("Tridiagonal matrix X", N, N, X, 0);
reconstruct_matrix("Reconstructed Row-Major Matrix", "Y", 3 * N - 2, Y, N, N, get_rm_0, 0);
dump_matrix("Tridiagonal matrix X", N, N, X, 1);
reconstruct_matrix("Reconstructed Row-Major Matrix", "Y", 3 * N - 2, Y, N, N, get_rm_1, 1);
puts("\n\n");
dump_matrix("Tridiagonal matrix X", N, N, X, 0);
reconstruct_matrix("Reconstructed Column-Major Matrix", "Z", 3 * N - 2, Z, N, N, get_cm_0, 0);
dump_matrix("Tridiagonal matrix X", N, N, X, 1);
reconstruct_matrix("Reconstructed Column-Major Matrix", "Z", 3 * N - 2, Z, N, N, get_cm_1, 1);
return 0;
}
There are many possible changes that could be made to this code.
Use functions get_[cr]m_[01]_idx() to get the array index in the vector. They would return -1 when the cell is off the tri-diagonal.
Use a modified vector (Y, Z) which has an extra element with value 0 at the start. Use const int *Y1 = &Y[1]; and then you can use: int val = Y1[get_rm_1_idx(r, c)]; to get the value.
Revise the get_[cr]m_[01]() functions to take the vector instead of using global variables Y and Z.
Rename the functions get_[cr]m_[01]() functions using get_[cr]m_[01]_val() to indicate that they get the value.
Add printing to report the index into the vectors Y and Z at which the value is found.
Output
Tridiagonal matrix X (6x6) 0-based:
c = 0 1 2 3 4 5
r = 0: { 1 2 0 0 0 0 }
r = 1: { 3 4 5 0 0 0 }
r = 2: { 0 6 7 8 0 0 }
r = 3: { 0 0 9 10 11 0 }
r = 4: { 0 0 0 12 13 14 }
r = 5: { 0 0 0 0 15 16 }
Vector Y (16) 0-based:
[ 0] = 1, [ 1] = 2, [ 2] = 3, [ 3] = 4, [ 4] = 5, [ 5] = 6, [ 6] = 7, [ 7] = 8,
[ 8] = 9, [ 9] = 10, [10] = 11, [11] = 12, [12] = 13, [13] = 14, [14] = 15, [15] = 16,
Reconstructed Row-Major Matrix (6x6) 0-based:
r = 0: { 1 2 0 0 0 0 }
r = 1: { 3 4 5 0 0 0 }
r = 2: { 0 6 7 8 0 0 }
r = 3: { 0 0 9 10 11 0 }
r = 4: { 0 0 0 12 13 14 }
r = 5: { 0 0 0 0 15 16 }
Tridiagonal matrix X (6x6) 1-based:
c = 1 2 3 4 5 6
r = 1: { 1 2 0 0 0 0 }
r = 2: { 3 4 5 0 0 0 }
r = 3: { 0 6 7 8 0 0 }
r = 4: { 0 0 9 10 11 0 }
r = 5: { 0 0 0 12 13 14 }
r = 6: { 0 0 0 0 15 16 }
Vector Y (16) 1-based:
[ 1] = 1, [ 2] = 2, [ 3] = 3, [ 4] = 4, [ 5] = 5, [ 6] = 6, [ 7] = 7, [ 8] = 8,
[ 9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14, [15] = 15, [16] = 16,
Reconstructed Row-Major Matrix (6x6) 1-based:
r = 1: { 1 2 0 0 0 0 }
r = 2: { 3 4 5 0 0 0 }
r = 3: { 0 6 7 8 0 0 }
r = 4: { 0 0 9 10 11 0 }
r = 5: { 0 0 0 12 13 14 }
r = 6: { 0 0 0 0 15 16 }
Tridiagonal matrix X (6x6) 0-based:
c = 0 1 2 3 4 5
r = 0: { 1 2 0 0 0 0 }
r = 1: { 3 4 5 0 0 0 }
r = 2: { 0 6 7 8 0 0 }
r = 3: { 0 0 9 10 11 0 }
r = 4: { 0 0 0 12 13 14 }
r = 5: { 0 0 0 0 15 16 }
Vector Z (16) 0-based:
[ 0] = 1, [ 1] = 3, [ 2] = 2, [ 3] = 4, [ 4] = 6, [ 5] = 5, [ 6] = 7, [ 7] = 9,
[ 8] = 8, [ 9] = 10, [10] = 12, [11] = 11, [12] = 13, [13] = 15, [14] = 14, [15] = 16,
Reconstructed Column-Major Matrix (6x6) 0-based:
r = 0: { 1 2 0 0 0 0 }
r = 1: { 3 4 5 0 0 0 }
r = 2: { 0 6 7 8 0 0 }
r = 3: { 0 0 9 10 11 0 }
r = 4: { 0 0 0 12 13 14 }
r = 5: { 0 0 0 0 15 16 }
Tridiagonal matrix X (6x6) 1-based:
c = 1 2 3 4 5 6
r = 1: { 1 2 0 0 0 0 }
r = 2: { 3 4 5 0 0 0 }
r = 3: { 0 6 7 8 0 0 }
r = 4: { 0 0 9 10 11 0 }
r = 5: { 0 0 0 12 13 14 }
r = 6: { 0 0 0 0 15 16 }
Vector Z (16) 1-based:
[ 1] = 1, [ 2] = 3, [ 3] = 2, [ 4] = 4, [ 5] = 6, [ 6] = 5, [ 7] = 7, [ 8] = 9,
[ 9] = 8, [10] = 10, [11] = 12, [12] = 11, [13] = 13, [14] = 15, [15] = 14, [16] = 16,
Reconstructed Column-Major Matrix (6x6) 1-based:
r = 1: { 1 2 0 0 0 0 }
r = 2: { 3 4 5 0 0 0 }
r = 3: { 0 6 7 8 0 0 }
r = 4: { 0 0 9 10 11 0 }
r = 5: { 0 0 0 12 13 14 }
r = 6: { 0 0 0 0 15 16 }
Assuming d is the main diagonal, a is the "above" diagonal, and b is the "below" diagonal:
+---+---+---+---+---+---+---+---+
| d | a | 0 | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+
| b | d | a | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+
| 0 | b | d | a | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+
| 0 | 0 | b | d | a | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | b | d | a | 0 | 0 |
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 | b | d | a | 0 |
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | b | d | a |
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 0 | b | d |
+---+---+---+---+---+---+---+---+
Note that the problem assumes indexes are "origin 1" (e.g. 1 <= i <= n) but C arrays want "origin 0" (e.g. 0 <= i < n)
We can use an "inner" struct to represent the Y array (e.g. elem_t) and the basic functions are:
#include <stdio.h>
#include <stdlib.h>
// sparse matrix Y vector
typedef struct {
int a; // above diagonal
int d; // main diagonal
int b; // below diagonal
} elem_t;
// sparse matrix
typedef struct {
int n;
elem_t *base;
} sparse_t;
// sparse_create -- create sparse tridiagonal matrix
sparse_t *
sparse_create(int n)
{
sparse_t *mtx = malloc(sizeof(*mtx));
mtx->n = n;
mtx->base = calloc(n,sizeof(*mtx->base));
return mtx;
}
// sparse_pointer -- point to sparse matrix element
int *
sparse_pointer(sparse_t *mtx,int coli,int rowi)
{
int n = mtx->n;
elem_t *eptr;
int *iptr = NULL;
// convert to origin 0
coli -= 1;
rowi -= 1;
do {
// check column bounds
if (coli < 0)
break;
if (coli >= n)
break;
// check row bounds
if (rowi < 0)
break;
if (rowi >= n)
break;
eptr = &mtx->base[coli];
// main diagonal
if (rowi == coli) {
iptr = &eptr->d;
break;
}
// above diagnonal
if ((rowi == (coli - 1)) && (coli > 0)) {
iptr = &eptr->a;
break;
}
// below diagnonal
if ((rowi == (coli + 1)) && (coli < (n - 1))) {
iptr = &eptr->b;
break;
}
} while (0);
return iptr;
}
// sparse_getval -- get matrix value
int
sparse_getval(sparse_t *mtx,int coli,int rowi)
{
int *iptr = sparse_pointer(mtx,coli,rowi);
int val;
if (iptr != NULL)
val = *iptr;
else
val = 0;
return val;
}
// sparse_setval -- set matrix value
void
sparse_setval(sparse_t *mtx,int coli,int rowi,int val)
{
int *iptr = sparse_pointer(mtx,coli,rowi);
if (iptr != NULL)
*iptr = val;
}
By contrast, a regular/full matrix would be:
#include <stdio.h>
#include <stdlib.h>
// regular/full matrix
typedef struct {
int n;
int *base;
} regmtx_t;
// regmtx_create -- create regular matrix
regmtx_t *
regmtx_create(int n)
{
regmtx_t *mtx = malloc(sizeof(*mtx));
mtx->n = n;
mtx->base = calloc(n * n,sizeof(*mtx->base));
return mtx;
}
// regmtx_pointer -- point to regular matrix element
int *
regmtx_pointer(regmtx_t *mtx,int coli,int rowi)
{
int *iptr = NULL;
// convert to origin 0
coli -= 1;
rowi -= 1;
do {
// check column bounds
if (coli < 0)
break;
if (coli >= mtx->n)
break;
// check row bounds
if (rowi < 0)
break;
if (rowi >= mtx->n)
break;
iptr = &mtx->base[(coli * mtx->n) + rowi];
} while (0);
return iptr;
}

Loop through a nested loop two-by two in C

I would like to loop through two arrays in a semi-zipped fashion, such that for as many entries as possible, the following pattern is observed:
arr1[i] arr2[j]
arr1[i] arr2[j+1]
arr1[i+1] arr2[j+2]
arr1[i+1] arr2[j+3]
....
For example, if len arr1 is 96 and len arr2 is 3, I would like to see
0 0
0 1
1 2
1 0
2 1
2 2
3 0
3 1
4 2
4 0
5 1
5 2
I'm having a little trouble getting the logic exactly right; any help would be greatly appreciated
Pseudocode:
i = 0;
for (x = 0; i < arr1.len; ++x) {
i = x / 2; // integer division
j = x % arr2.len;
// use arr1[i] and arr2[j]
}
Use integer division to repeat a value multiple times before moving on to the next value (e.g. 0 0 1 1 2 2 3 3 ...), where the number of times you want to repeat a value is equal to the denominator.
Use modulo division to repeat a sequence of values indefinitely (e.g. 0 1 2 0 1 2 0 1 2 ...), where the number of items in the sequence is equal to the denominator.
If I have understood you correctly you need a loop like the one shown in the demonstrative program below.
#include <stdio.h>
#define N 10
#define M 3
int main( void )
{
int a[N];
int b[N];
for ( int i = 0; i < N; i++ ) a[i] = i;
for ( int i = 0; i < M; i++ ) b[i] = i;
for (int i = 0, j = 0, k = 1; i < N; i += k ^= 1, j = ( j + 1 ) % M)
{
printf( "%d %d\n", a[i] , b[j] );
}
}
The program output is
0 0
0 1
1 2
1 0
2 1
2 2
3 0
3 1
4 2
4 0
5 1
5 2
6 0
6 1
7 2
7 0
8 1
8 2
9 0
9 1

Expression out of bounds on MATLAB with HDL coder app

I try to get the VHDL code corresponding to my simulation on MATLAB with HDL coder app, but I get a first error at the line 25 when I build the MATLAB code on the HDL coder app:
Index expression out of bounds. Attempted to access element 15. The valid range is 1-1.
I don't understand because the simulation on MATLAB works and I don't get this error.
function U_p = HDL_decoder_function(r)
H1 = [ 1 0 0 0 1 0 1 1 0 0 0 0 0 0 0 ];
H = 0;
S_in_rows = 0;
Sm = 0;
S = 0;
f_in_column = 0;
f = 0;
f_largest = 0;
f_nth_largest = 0;
% Declaration of the parity-check matrix
% Fill the first row to prepare the shift in the H matrix
for i = 1 : 15
H( 1, i ) = H1(i);
end
% Fill all the other rows with the shift
for j = 2 : 15
for i = 1 : 15
if( i == 1 )
H( j, i) = H( j-1, 15); % first error
else
H( j, i) = H( j-1, i-1);
end
end
end
H;
% Start of the bit-flipping algorithm
for k = 1 : 20 % Authorize 20 executions maximum of the statements of the algorithm
% Calculate the syndrome S = r^T * H
for j = 1 : 15
for i = 1 : 15
S_in_rows(i) = and( r(i), H( j, i) );
end
for i = 1 : 15
Sm = sum(S_in_rows);
end
if rem(Sm, 2) == 1
S(j) = 1;
else
S(j) = 0;
end
end
S;
% Go out from the loop when syndrome S = 0
if S == 0
U_p = r;
break
end
if k == 20
disp('Decoding fail')
U_p = [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ];
end
% Find the number f of failed syndrome bits for every received bits r
for i = 1 : 15
f(i) = 0; % Declaration
end
for i = 1 : 15
for j = 1 : 15
f_in_column = and( S(j), H( j, i) );
if f_in_column == 1
f(i) = f(i)+1;
end
end
end
f;
% Flip the the rth bit corresponding to the first largest number of error in f
f_largest = 0;
for i = 1 : 15
if f(i) > f_largest
f_largest = f(i); % Save the number of error
f_nth_largest = i; % Save the position of f_largest
end
end
f_largest;
f_nth_largest;
r(f_nth_largest) = not(r(f_nth_largest));
r;
U_p = r;
end
I don't use the HDL coder, but I have a likely cause. From your code:
H = 0;
% Fill the first row to prepare the shift in the H matrix
for i = 1 : 15
H( 1, i ) = H1(i);
end
Here, you define H to be a single integer, than use it as if it was a matrix. This is bad practice in Matlab (though will run) since each time you write to an array location that doesn't exist, Matlab creates a new array, then copy the current content to it, free the previous content and finally make the assignation. When it comes to VHDL, the variable size must be fixed and known in advance, there is no dynamic array in hardware.
You should pre-allocate your variables to the right dimensions before you use them. Simply change H = 0 to
H = zeros(15, 15);
Note that similarly, other variables are not initialized to the right size, including S, S_in_row and f.

Convert COO to CSR format in c++

I have a matrix in the COO format. More specifically, there are three matrices row_index, column_index, value. Can you help me to convert this matrix format in CSR format with an efficient, not computationally expensive way, using C language? Are there libraries for this purpose?
Example:
COO format:
row_index col_index value
1 1 1
1 2 -1
1 3 -3
2 1 -2
2 2 5
3 3 4
3 4 6
3 5 4
4 1 -4
4 3 2
4 4 7
5 2 8
5 5 -5
I know this is an old thread, but, assuming the COO data is (i,j) ordered/sorted, as you show, a sequential algorithm to convert from COO to CSR is:
int main()
{
// Example from Wikipedia (https://en.wikipedia.org/wiki/Sparse_matrix)
// Matrix:
// 10 20 0 0 0 0
// 0 30 0 40 0 0
// 0 0 50 60 70 0
// 0 0 0 0 0 80
// Expected output:
// csr_val: 10 20 30 40 50 60 70 80
// csr_col: 0 1 1 3 2 3 4 5
// csr_row: 0 2 4 7 8
const int nnz = 8; // number of non-zero elements
const int rows = 4; // number of matrix rows
const int cols = 6; // number of matrix columns
// coo data:
double coo_val[nnz] = { 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0 };
int coo_row[nnz] = { 0, 0, 1, 1, 2, 2, 2, 3 };
int coo_col[nnz] = { 0, 1, 1, 3, 2, 3, 4, 5 };
// coo to csr:
double csr_val[nnz] = { 0 };
int csr_col[nnz] = { 0 };
int csr_row[rows + 1] = { 0 };
for (int i = 0; i < nnz; i++)
{
csr_val[i] = coo_val[i];
csr_col[i] = coo_col[i];
csr_row[coo_row[i] + 1]++;
}
for (int i = 0; i < rows; i++)
{
csr_row[i + 1] += csr_row[i];
}
}
Notice that, assuming the COO data is (i,j) ordered/sorted, csr_col = coo_col and csr_val = coo_val, so you just need to obtain csr_row, and that is as simples as:
int csr_row[rows + 1] = { 0 };
for (int i = 0; i < nnz; i++)
csr_row[coo_row[i] + 1]++;
for (int i = 0; i < rows; i++)
csr_row[i + 1] += csr_row[i];
So, in conclusion, you can easily achieve what you want with the 5 lines of code presented above.
Final note:
The proposed method has no considerations for duplicated COO entries.
Intel MKL documentation (for mkl_csrcoo) states:
Converts a sparse matrix in the CSR format to the coordinate format
and vice versa.
And according to the above link you should set job:
if job(1)=1, the matrix in the coordinate format is converted to the CSR format.
An implementation of this conversion is included in scipy (open source: BSD-licensed), the function coo_tocsr in particular. It is in C++, but this is only in order to template the data and index types, and in order to initialise a data structure, so it can easily be transformed into C code.

Resources