Program to print and display identity matrix in C - c

i am having trouble writing a program that prints a matrix, and then I generate the identity matrix. Here is my ccode below and any help would be greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int PrintMatrix(int dim, double matrix[dim][dim]);
int main()
int PrintMatrix(int dim, double matrix[dim][dim]) {
int aa, bb;
for (aa = 0; aa <= dim; aa++) {
for (bb = 0; bb <= dim; bb++) {
printf("%lf ", matrix[aa][bb]);
}
printf("\n");
}
}
double TestMatrix[7][7] = {
{1,0,0,0,0,0,0},
{0,1,0,0,0,0,0},
{0,0,1,0,0,0,0},
{0,0,0,1,0,0,0},
{0,0,0,0,1,0,0},
{0,0,0,0,0,1,0},
{0,0,0,0,0,0,1}
};
PrintMatrix(7, TestMatrix);
return 0;

Your code won't compile successfully.
After main there is no opening brace.
You are defining function inside main, which is an issue.
Check for parentheses in whole code.
Fixed the loop controls from <= to <.
Here is the modified code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int PrintMatrix(int dim, double matrix[dim][dim]);
int main()
{
double TestMatrix[7][7] = {
{1,0,0,0,0,0,0},
{0,1,0,0,0,0,0},
{0,0,1,0,0,0,0},
{0,0,0,1,0,0,0},
{0,0,0,0,1,0,0},
{0,0,0,0,0,1,0},
{0,0,0,0,0,0,1},
};
PrintMatrix(7, TestMatrix);
return 0;
}
int PrintMatrix(int dim, double matrix[dim][dim]) {
int aa, bb;
for (aa = 0; aa < dim; aa++) {
for (bb = 0; bb < dim; bb++) {
printf("%lf ", matrix[aa][bb]);
}
printf("\n");
}
}

The code in the question is an appalling non-compiling mess. One of the comments is:
It still isn't returning the identity for dim = 2 up to 7; any thoughts?
As BluePixy hinted, if you lie to your compiler about the size of the input matrix to the function, for example by passing a 7x7 matrix but telling that it has a 3x3 matrix, it gets its revenge by printing different information from what you wanted. Don't lie to the compiler!
If you want to print identity matrices of sizes 1..7 from a 7x7 matrix, tell the compiler (function) both the actual size of the matrix and the size you want printed. For an identity matrix, you don't actually need the original matrix — you could synthesize the data.
#include <stdio.h>
static void printIdentityMatrix(int size)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
printf("%4.1f", (i == j) ? 1.0 : 0.0);
putchar('\n');
}
}
int main(void)
{
for (int i = 1; i < 8; i++)
printIdentityMatrix(i);
return 0;
}
For printing the top left square subset of an arbitrarily sized square matrix, you must pass both the size of the data to be printed and the actual size of the matrix.
#include <assert.h>
#include <stdio.h>
static void PrintMatrix(int size, int dim, double matrix[dim][dim])
{
assert(size <= dim);
for (int aa = 0; aa < size; aa++)
{
for (int bb = 0; bb < size; bb++)
printf("%lf ", matrix[aa][bb]);
putchar('\n');
}
}
int main(void)
{
double TestMatrix[7][7] =
{
{1,0,0,0,0,0,0},
{0,1,0,0,0,0,0},
{0,0,1,0,0,0,0},
{0,0,0,1,0,0,0},
{0,0,0,0,1,0,0},
{0,0,0,0,0,1,0},
{0,0,0,0,0,0,1},
};
for (int i = 1; i < 8; i++)
{
PrintMatrix(i, 7, TestMatrix);
putchar('\n');
}
return 0;
}
Printing an arbitrary rectangular submatrix of an arbitrarily sized rectangular matrix requires many more function parameters (7 if I am counting correctly:
void PrintSubMatrix(int x_off, int y_off, int x_len, int y_len, int x_size, int y_size,
double matrix[x_size][y_size]);
and that's before you specify the file stream to write on.
#include <assert.h>
#include <stdio.h>
static void PrintSubMatrix(int x_off, int y_off, int x_len, int y_len, int x_size, int y_size,
double matrix[x_size][y_size])
{
assert(x_off >= 0 && x_off < x_size && x_off + x_len <= x_size);
assert(y_off >= 0 && y_off < y_size && y_off + y_len <= y_size);
printf("SubMatrix size %dx%d at (%d,%d) in M[%d][%d]\n",
x_len, y_len, x_off, y_off, x_size, y_size);
for (int x = x_off; x < x_off + x_len; x++)
{
for (int y = y_off; y < y_off + y_len; y++)
printf("%4.1f ", matrix[x][y]);
putchar('\n');
}
putchar('\n');
}
int main(void)
{
double TestMatrix[7][9] =
{
{ 1, 2, 3, 4, 3, 2, 1, 2, 3 },
{ 2, 1, 9, 8, 4, 6, 0, 0, 1 },
{ 3, 0, 8, 7, 5, 5, 0, 0, 1 },
{ 4, 0, 5, 6, 6, 8, 4, 4, 4 },
{ 5, 0, 1, 4, 7, 9, 0, 0, 1 },
{ 6, 0, 1, 0, 8, 1, 0, 0, 1 },
{ 7, 0, 0, 0, 9, 0, 1, 0, 1 },
};
PrintSubMatrix(0, 0, 7, 9, 7, 9, TestMatrix);
for (int i = 1; i < 4; i++)
{
for (int j = 2; j < 4; j++)
PrintSubMatrix(i, j, 3 + j - i, i + j, 7, 9, TestMatrix);
}
return 0;
}
Sample run:
SubMatrix size 7x9 at (0,0) in M[7][9]
1.0 2.0 3.0 4.0 3.0 2.0 1.0 2.0 3.0
2.0 1.0 9.0 8.0 4.0 6.0 0.0 0.0 1.0
3.0 0.0 8.0 7.0 5.0 5.0 0.0 0.0 1.0
4.0 0.0 5.0 6.0 6.0 8.0 4.0 4.0 4.0
5.0 0.0 1.0 4.0 7.0 9.0 0.0 0.0 1.0
6.0 0.0 1.0 0.0 8.0 1.0 0.0 0.0 1.0
7.0 0.0 0.0 0.0 9.0 0.0 1.0 0.0 1.0
SubMatrix size 4x3 at (1,2) in M[7][9]
9.0 8.0 4.0
8.0 7.0 5.0
5.0 6.0 6.0
1.0 4.0 7.0
SubMatrix size 5x4 at (1,3) in M[7][9]
8.0 4.0 6.0 0.0
7.0 5.0 5.0 0.0
6.0 6.0 8.0 4.0
4.0 7.0 9.0 0.0
0.0 8.0 1.0 0.0
SubMatrix size 3x4 at (2,2) in M[7][9]
8.0 7.0 5.0 5.0
5.0 6.0 6.0 8.0
1.0 4.0 7.0 9.0
SubMatrix size 4x5 at (2,3) in M[7][9]
7.0 5.0 5.0 0.0 0.0
6.0 6.0 8.0 4.0 4.0
4.0 7.0 9.0 0.0 0.0
0.0 8.0 1.0 0.0 0.0
SubMatrix size 2x5 at (3,2) in M[7][9]
5.0 6.0 6.0 8.0 4.0
1.0 4.0 7.0 9.0 0.0
SubMatrix size 3x6 at (3,3) in M[7][9]
6.0 6.0 8.0 4.0 4.0 4.0
4.0 7.0 9.0 0.0 0.0 1.0
0.0 8.0 1.0 0.0 0.0 1.0
It would be better if the code was fixed not to print a blank at the end of each line; that's left as an exercise for the reader.

Related

How should I make this logic in C?

There is this linear system given by the following 2d array:
1.0 0.0 -1.0 -4.9 -5.9 -6.9 -7.9
0.0 1.0 2.0 4.4 5.4 6.4 7.4
0.0 0.0 0.0 5.7 5.7 -3.3 -3.3
0.0 0.0 0.0 2.9 2.9 2.9 2.9
0.0 0.0 0.0 7.0 -1.0 -3.0 -3.0
0.0 0.0 -20.0 -65.9 -89.9 -100.9 128.9
Whenever I get a 0 in my main diagonal (when row equals column), I want to change the order of the rows, so there's no zeroes on my main diagonal.
In this case, the row 2(counting from 0) should be traded with row 5 (also counting from 0) because with this, there is no 0s on the main diagonal.
I'm already doing that, but I'm "deleting" the first line and appending it on the end of the linear system. How should I make this logic to know where to exactly trade the rows?
The code is as follows:
void change_order(double linear[6][7], unsigned int qty) {
double aux[100];
// dynamically create an array of pointers of size `m`
double **matrix = (double **)malloc((qty + 1) * sizeof(double *));
// dynamically allocate memory of size `n` for each row
for (int r = 0; r < qty+ 1; r++) {
matrix[r] = (double *)malloc((qty + 1) * sizeof(double));
}
for (int i = 0; i < qty; i++) {
for (int j = 0; j < qty+ 1; j++) {
if (i == 0)
aux[j] = linear[i][j];
}
}
for (int i = 0; i < qty; i++) {
for (int j = 0; j < qty+ 1; j++) {
matrix[i][j] = linear[i][j];
}
}
remove_line(matrix, 0, qty);
for (int i = 0; i < qty; i++) {
for (int j = 0; j < qty+ 1; j++) {
linear[i][j] = matrix[i][j];
}
}
for (int i = 0; i < qty; i++) {
for (int j = 0; j < qty+ 1; j++) {
if (i == qty- 1) {
linear[i][j] = aux[j];
}
}
}
}
void remove_line(double ** linear, int row, unsigned int qty) {
qty--;
free(linear[row]);
while (row < qty) {
linear[row] = linear[row + 1];
row++;
}
}
int main() {
double matrix[][7] = {
{1.0, 0.0, -1.0, -4.9, -5.9, -6.9, -7.9},
{0.0, 1.0, 2.0, 4.4, 5.4, 6.4, 7.4},
{0.0 , 0.0, 0.0, 5.7, 5.7, -3.3, -3.3},
{0.0 , 0.0, 0.0, 2.9, 2.9, 2.9, 2.9},
{0.0 , 0.0, 0.0, 7.0, -1.0, -3.0, -3.0},
{0.0 , 0.0, -20.0, -65.9, -89.9, -100.9, 128.9}
};
change_order(matrix, 6);
}
Example input:
0 3 2 28
4 0 2 24
2 3 0 16
4 2 1 0
Can be exchanged for:
4 0 2 24
2 3 0 16
4 2 1 0
0 3 2 28
If I'm understanding your requirements correctly, would you please try the following:
#include <stdio.h>
#include <stdlib.h>
#define ROWS 6
#define COLS 7
/*
* search for a trade line to be swapped below the n'th row
*/
int search_trade(double matrix[][COLS], int qty, int n)
{
for (int i = n + 1; i < qty; i++) {
if (matrix[i][n] != 0.0) {
return i; // i'th row is a nice trade
}
}
return -1; // not found
}
/*
* swap m'th row and n'th row
*/
void swap(double matrix[][COLS], int qty, int m, int n)
{
int j;
double tmp;
for (j = 0; j < qty + 1; j++) {
tmp = matrix[m][j];
matrix[m][j] = matrix[n][j];
matrix[n][j] = tmp;
}
}
void change_order(double linear[][COLS], int qty) {
for (int i = 0; i < qty; i++) {
if (linear[i][i] == 0.0) { // found 0 in the diagonal
int k = search_trade(linear, qty, i); // search for the trade row
if (k < 0) { // no applicable trade
fprintf(stderr, "cannot find the row to swap. abort.\n");
exit(1);
} else {
swap(linear, qty, i, k); // swap i'th row and k'th row
}
}
}
}
/*
* print the elements of the matrix
*/
void matprint(double matrix[][COLS], int qty)
{
for (int i = 0; i < qty; i++) {
for (int j = 0; j < qty + 1; j++) {
printf("%.2f%s", matrix[i][j], j == qty ? "\n" : " ");
}
}
printf("\n");
}
int main() {
double matrix[][COLS] = {
{1.0, 0.0, -1.0, -4.9, -5.9, -6.9, -7.9},
{0.0, 1.0, 2.0, 4.4, 5.4, 6.4, 7.4},
{0.0 , 0.0, 0.0, 5.7, 5.7, -3.3, -3.3},
{0.0 , 0.0, 0.0, 2.9, 2.9, 2.9, 2.9},
{0.0 , 0.0, 0.0, 7.0, -1.0, -3.0, -3.0},
{0.0 , 0.0, -20.0, -65.9, -89.9, -100.9, 128.9}
};
matprint(matrix, ROWS);
change_order(matrix, ROWS);
matprint(matrix, ROWS);
}
Output:
0.00 1.00 2.00 4.40 5.40 6.40 7.40
0.00 0.00 0.00 5.70 5.70 -3.30 -3.30
0.00 0.00 0.00 2.90 2.90 2.90 2.90
0.00 0.00 0.00 7.00 -1.00 -3.00 -3.00
0.00 0.00 -20.00 -65.90 -89.90 -100.90 128.90
1.00 0.00 -1.00 -4.90 -5.90 -6.90 -7.90
0.00 1.00 2.00 4.40 5.40 6.40 7.40
0.00 0.00 -20.00 -65.90 -89.90 -100.90 128.90
0.00 0.00 0.00 2.90 2.90 2.90 2.90
0.00 0.00 0.00 7.00 -1.00 -3.00 -3.00
0.00 0.00 0.00 5.70 5.70 -3.30 -3.30
You'll see the 2nd row and the 5th row are swapped.
The main concept is:
Seek the diagonal elements for value 0.
If 0 is found, search for a trade row which has a non-zero value in the same column.
If no trade rows are found, the program prints an error message and aborts.
If a trade row is found, swap the rows.
[Edit]
Answering your comment, the code assumes the count of cols == count of rows + 1.
As your provided example has 4x4 matrix, let me add an extra column as:
double matrix[][COLS] = {
{0, 3, 2, 28, -1},
{4, 0, 2, 24, -1},
{2, 3, 0, 16, -1},
{4, 2, 1, 0, -1}
};
(Please note the value -1 is a dummy value and meaningless so far.)
And modify the #define lines as:
#define ROWS 4
#define COLS 5
Then the program will output:
0.00 3.00 2.00 28.00 -1.00
4.00 0.00 2.00 24.00 -1.00
2.00 3.00 0.00 16.00 -1.00
4.00 2.00 1.00 0.00 -1.00
4.00 0.00 2.00 24.00 -1.00
0.00 3.00 2.00 28.00 -1.00
4.00 2.00 1.00 0.00 -1.00
2.00 3.00 0.00 16.00 -1.00
which shows the rows are properly rearranged having no 0 values in the diagonal.
(BTW your expected result breaks having 0 in the diagonal in the last row.)
**You can make a main function like as follows:
//after passing the linear function
int i,j, temp; // declare i and j as global variables**
for(i=0,i<qty+1,i++)
{
for (j=0;j<qty+1;j++)
{
if(i==j & matrix[i][j]==0)
{
remove_line;
temp = i;
break;
}
}
} // here we are looking for a zero in the diagonal.
for (;i<qty+1;i++)
{
if(matrix[i][j]!=0)
{
matrix[temp][j] = linear[i][j]
}
}
// **here we are increasing the rows till we get a non zero element and then
interchanging the values.**

Making a 2d array from a text file

Im working with a sparse matrix and im given a text file like this:
0 3 1.2
2 5 3.2
3 0 2.1
3 5 4.2
4 5 2.2
0 0 5.2
Basically the way it works is the number 1.2 goes on the position [0] [3] and the elements of the matriz that are not mentioned stay at 0, so in this case it should look like this:
5.2 0 0 1.2 0 0
0 0 0 0 0 0
0 0 0 0 0 3.2
2.1 0 0 0 0 4.2
0 0 0 0 0 2.2
OP wrote this in the comments:
Im so sorry but my teacher clarified everything just now... it turns out that, for each line, the first number is the row, the second the column and the third the element.with the example i have above, 1.2 has to go in the position [0][3]. The matrix does not have to be square.
This makes every thing different. If you don't know the dimensions of the
matrix, then you have to read everything first, then calculate the matrix
dimensions, allocate space for the matrix and then fill it with the values.
I'd do this:
#include <stdio.h>
#include <stdlib.h>
#define BLOCK 1024
struct matrix_info {
int col;
int row;
double val;
};
void free_matrix(double **matrix, size_t rows)
{
if(matrix == NULL)
return;
for(size_t i = 0; i < rows; ++i)
free(matrix[i]);
free(matrix);
}
double **readmatrix(const char *fname, size_t *rows, size_t *cols)
{
if(fname == NULL || rows == NULL || cols == NULL)
return NULL;
double **matrix = NULL;
struct matrix_info *info = NULL;
size_t mi_idx = 0; // matrix info index
size_t mi_size = 0;
FILE *fp = fopen(fname, "r");
if(fp == NULL)
{
fprintf(stderr, "Cannot open %s\n", fname);
return NULL;
}
*rows = 0;
*cols = 0;
for(;;)
{
if(mi_idx >= mi_size)
{
struct matrix_info *tmp = realloc(info, (mi_size + BLOCK) * sizeof *info);
if(tmp == NULL)
{
fprintf(stderr, "not enough memory\n");
free(info);
fclose(fp);
return NULL;
}
info = tmp;
mi_size += BLOCK;
}
int ret = fscanf(fp, "%d %d %lf", &info[mi_idx].row, &info[mi_idx].col,
&info[mi_idx].val);
if(ret == EOF)
break; // end of file reached
if(ret != 3)
{
fprintf(stderr, "Error parsing matrix\n");
free(info);
fclose(fp);
return NULL;
}
if(*rows < info[mi_idx].row)
*rows = info[mi_idx].row;
if(*cols < info[mi_idx].col)
*cols = info[mi_idx].col;
mi_idx++;
}
fclose(fp);
// mi_idx is now the length of info
// *cols and *rows have the largest index
// for the matrix, hence the dimension is (rows + 1) x (cols + 1)
(*cols)++;
(*rows)++;
// allocating memory
matrix = calloc(*rows, sizeof *matrix);
if(matrix == NULL)
{
fprintf(stderr, "Not enough memory\n");
free(info);
return NULL;
}
for(size_t i = 0; i < *rows; ++i)
{
matrix[i] = calloc(*cols, sizeof **matrix);
if(matrix[i] == NULL)
{
fprintf(stderr, "Not enough memory\n");
free(info);
free_matrix(matrix, *rows);
return NULL;
}
}
// populating matrix
for(size_t i = 0; i < mi_idx; ++i)
{
int r,c;
r = info[i].row;
c = info[i].col;
matrix[r][c] = info[i].val;
}
free(info);
return matrix;
}
int main(void)
{
const char *fn = "/tmp/matrix.txt";
size_t rows, cols;
double **matrix = readmatrix(fn, &rows, &cols);
if(matrix == NULL)
return 1;
for(size_t i = 0; i < rows; ++i)
{
for(size_t j = 0; j < cols; ++j)
printf("%0.3f ", matrix[i][j]);
puts("");
}
free_matrix(matrix, rows);
return 0;
}
The output is (for a file with your sample data)
5.200 0.000 0.000 1.200 0.000 0.000
0.000 0.000 0.000 0.000 0.000 0.000
0.000 0.000 0.000 0.000 0.000 3.200
2.100 0.000 0.000 0.000 0.000 4.200
0.000 0.000 0.000 0.000 0.000 2.200
So a quick explanation of what I'm doing:
I read the file and store in an dynamically allocated array the information
about the column, the row and the value. This information is stored in the
struct matrix_info *info.
The idea is that I read every line and extract the three values. While I read
the file, I also store the largest index for the column and the row
...
if(*rows < info[mi_idx].row)
*rows = info[mi_idx].row;
if(*cols < info[mi_idx].col)
*cols = info[mi_idx].col;
...
so when the file is read, I know the dimensions of the matrix. Now all values
with their row & column are stored in the info array, so the next step is to
allocate memory for the matrix and fill the values based based on the info[i]
entries.
for(size_t i = 0; i < mi_idx; ++i)
{
int r,c;
r = info[i].row;
c = info[i].col;
matrix[r][c] = info[i].val;
}
At the end I free the memory for info and return the matrix.
Another interesting part is this:
if(mi_idx >= mi_size)
{
struct matrix_info *tmp = realloc(info, (mi_size + BLOCK) * sizeof *info);
if(tmp == NULL)
{
fprintf(stderr, "not enough memory\n");
free(info);
fclose(fp);
return NULL;
}
info = tmp;
mi_size += BLOCK;
}
Because you mentioned that the only thing you know about the matrix is that it
might contain up to 10000 elements, then the input file might be very big.
Instead of reallocating memory for the info elements on every loop, I allocate
chunks of 1024 (BLOCK) info elements at a time. Thus once a block is full,
the next block is allocated and so on. So I call realloc only every 1024
iterations.
you need use in first :
float* sparseMatrix = malloc(sizeof(float) * 10000);
You start read the file and after the first line read you know the nomber of colums and the number of row is the number of line read. After you can reduce the matrix if you want.
free(sparseMatrix );
sparseMatrix = malloc(sizeof(float) * nbRow*nbColum);
You simply don't have enough information to construct an appropriate matrix. In your cited case, you know you have AT LEAST 5 rows and AT LEAST 6 columns, but you don't know exactly how many rows m and columns n are in your matrix. So for your given input:
0 3 1.2
2 5 3.2
3 0 2.1
3 5 4.2
4 5 2.2
0 0 5.2
You could have a 5x6 matrix as:
5.2 0.0 0.0 1.2 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 3.2
2.1 0.0 0.0 0.0 0.0 4.2
0.0 0.0 0.0 0.0 0.0 2.2
Or you could have a 10x6 matrix as:
5.2 0.0 0.0 1.2 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 3.2
2.1 0.0 0.0 0.0 0.0 4.2
0.0 0.0 0.0 0.0 0.0 2.2
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
This ambiguity is a problem as the first matrix is vastly different that the second.
Also, the point of a sparse matrix is to be efficient with memory and/or processing time. If you allocate a full array of m rows and n columns then you have a dense matrix representation instead.
There's no real way of knowing what's in a file unless you completely read the file yourself first.
Since you know that there will be max 10k elements, you can statically allocate an array of that size first, and then load the numbers into the until you parse an EOF.
float sparseMatrix[10000];
It just means that your program will always allocate the space for 10k elements regardless of how many elements are actually in the array. If you assume that each element takes up 4 bytes, then you'll only be using ~40kB of memory. This is probably the easiest solution.
The other option would be to read the file fully, figure out the required size, and dynamically allocate that size, then read through the whole file again whilst populating the elements.
// Assume numberOfElements was determined by reading through the file first
float* sparseMatrix = malloc(sizeof(float) * numberOfElements);
Though this method will use less memory, it requires two full reads of the file + the overhead of calling malloc.
You can measure the number of rows and columns and then define your 2d array. Of course, this will increase the time complexity! If you don't care about the size of the memory, you can define your array with the max columns and rows! So you should choose between big time complexity and big memory size.

C: Finding maximum average of a 2 dimensional array

The output that I want is the max of an average score and which row is that for example:
9.33(avg) 4(row)
9.33(avg) 5(row)
But my output is this:
9.33 0
9.33 4
9.33 5
Can anyone explain for me why my output is like this and how I could fix it?
#include <stdio.h>
#include <string.h>
#define D 3
#define C 10
int main()
{
float num[D][C] =
{
{5.0, 8.0, 7.5, 4.5, 9.0, 9.0, 6.5, 3.0, 4.5, 8.5},
{6.0, 8.5, 7.0, 5.0, 9.5, 9.5, 6.5, 2.5, 5.0, 7.5},
{5.5, 8.0, 6.5, 7.5, 9.5, 9.5, 6.5, 4.0, 5.5, 9.5},
};
int i, j,e,l;
float d,a,b,c,max,k,x,y,z,o;
float p1,p2,p3,p4;
k=0;
max=0;
for(j=0; j<10; j++)
{
a=num[0][j];
b=num[1][j];
c=num[2][j];
d=(a+b+c)/3;
if(max<=d )
{
for(l=0; l<10; l++)
{
x=num[0][l];
y=num[1][l];
z=num[2][l];
o=(x+y+z)/3;
if(max<o)
{
max=o;
}
}
printf("%0.2f %d\n",max,j);
}
}
}
some suggestions were given in the comments already. define the size of the arrays and reuse the defines in the loops do avoid overflows.
at first calculate the averages and memorize the maximum value.
then you can easily output them comparing your maximum value to the memorized avg values.
#define D 3
#define C 10
float num[D][C] = {
{5.0, 8.0, 7.5, 4.5, 9.0, 9.0, 6.5, 3.0, 4.5, 8.5},
{6.0, 8.5, 7.0, 5.0, 9.5, 9.5, 6.5, 2.5, 5.0, 7.5},
{5.5, 8.0, 6.5, 7.5, 9.5, 9.5, 6.5, 4.0, 5.5, 9.5},
};
float avg[C]; /*will hold all the average values*/
float max = 0; /*will hold the maximum vlaue*/
int i, j;
for (i = 0; i < C; i++) {
float sum = 0;
/*sum columns*/
for (j = 0; j < D; j++) {
sum += num[j][i];
}
/*memorize calculated avg*/
avg[i] = sum / D;
/*check if maximum*/
if (max < avg[i])
max = avg[i];
}
/*output index and average*/
for (i = 0; i < C; i++)
if (avg[i] == max)
printf("%0.2f %d\n",max,i);

MPI in c. I don't receive what I send

I am new in MPI. I am trying to write some simple code. Here it is:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <mpi.h>
#include <unistd.h>
#define ONE 0
#define TWO 1
int main(int argc, char * argv[])
{
int dimension = 5;
float ** matrix;
float * mat1;
float * mat2;
int i,j,numNeighbor, processReceived,rank,size,retval;
int k = 0;
retval = MPI_Init(&argc, &argv);
MPI_Request sendRequest[2], recvRequest[2];
MPI_Status status[2];
MPI_Datatype row;
MPI_Type_vector(dimension, 1, dimension, MPI_FLOAT, &row);
MPI_Type_commit(&row);
if(retval != MPI_SUCCESS)
{
MPI_Abort(MPI_COMM_WORLD, retval);
return EXIT_FAILURE;
}
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
mat1 = malloc(dimension*sizeof(float));
mat2 = malloc(dimension*sizeof(float));
matrix = malloc(dimension*sizeof(float*));
for(i=0; i<dimension; i++)
{
matrix[i] = malloc(dimension*sizeof(float));
}
printf("MATRIX OF RANK %d\n", rank);
for(i=0; i<dimension; i++)
{
for(j=0; j<dimension; j++)
{
matrix[i][j] = (float)(rank+1)*(i*2+j);
printf("%2.1f ",matrix[i][j]);
}
printf("\n");
}
printf("\n");
MPI_Isend(&(matrix[0][0]), 1, row, 1-rank, rank, MPI_COMM_WORLD, sendRequest + ONE);
MPI_Isend(&(matrix[0][0]), dimension, MPI_FLOAT, 1-rank, rank, MPI_COMM_WORLD, sendRequest + TWO);
MPI_Irecv(mat1,dimension, MPI_FLOAT, 1-rank, 1-rank, MPI_COMM_WORLD, recvRequest + ONE);
MPI_Irecv(mat2,dimension, MPI_FLOAT, 1-rank, 1-rank, MPI_COMM_WORLD, recvRequest + TWO);
for(i=0; i<2; i++)
{
MPI_Waitany(2,recvRequest, &processReceived, status);
printf("Process Received : %d of rank : %d\n", processReceived,rank);
if(processReceived == ONE)
{
printf("%d ",rank);
for(j=0; j<dimension; j++) printf("# %6.1f ",mat1[j]);
printf("\n");
}
if(processReceived == TWO)
{
printf("%d ",rank);
for(j=0; j<dimension; j++) printf("# %6.1f ",mat2[j]);
printf("\n");
}
}
MPI_Waitall(2, sendRequest, status);
free(mat1);
free(mat2);
for(i=0;i<dimension;i++) free(matrix[i]);
free(matrix);
MPI_Type_free(&row);
MPI_Finalize();
return 0;
}
This is my output:
MATRIX OF RANK 1
0.0 2.0 4.0 6.0 8.0
4.0 6.0 8.0 10.0 12.0
8.0 10.0 12.0 14.0 16.0
12.0 14.0 16.0 18.0 20.0
16.0 18.0 20.0 22.0 24.0
MATRIX OF RANK 0
0.0 1.0 2.0 3.0 4.0
2.0 3.0 4.0 5.0 6.0
4.0 5.0 6.0 7.0 8.0
6.0 7.0 8.0 9.0 10.0
8.0 9.0 10.0 11.0 12.0
Process Received : 0 of rank : 0
0 # 0.0 # 0.0 # 12.0 # 14.0 # 16.0
Process Received : 1 of rank : 0
0 # 0.0 # 0.0 # 12.0 # 14.0 # 16.0
Process Received : 0 of rank : 1
1 # 0.0 # 0.0 # 6.0 # 7.0 # 8.0
Process Received : 1 of rank : 1
1 # 0.0 # 0.0 # 6.0 # 7.0 # 8.0
What I think I am doing with this program is that I send one row and one column of each process to the other process. Then I print whatever i received in each process. But as you can see this is not the output i thought i would have. What i am waiting for is something like:
example of output:
Process Received : 0 of rank : 0
0 # 0.0 # 2.0 # 4.0 # 6.0 # 8.0
Process Received : 1 of rank : 0
0 # 0.0 # 4.0 # 8.0 # 12.0 # 16.0
Can anyone explain me what i haven't got very well? This is the only function that i use so you can run it in your own machines. For this example you can use only 2 processes.
mpiexec -n 2 ./name_exe
The issue comes from the fact that the data storage in matrix isn't linear. As it is defined in the code at the moment, matrix is an array of pointers, all of which point to some independent memory segments.
However, your code assumes that &matrix[0][0] points to the beginning of a linearised row-major matrix.
Well, to solve the issue, you simply need to comply with this by allocating matrix the following way:
matrix = malloc(dimension*sizeof(float*)); //nothing new here
matrix[0] = malloc(dimension*dimension*sizeof(float));
for(i=1; i<dimension; i++) matrix[i]=matrix[i-1]+dimension;
Then you use matrix exactly as before, but for the freeing part, which becomes:
free(matrix[0]);
free(matrix);
With this, the code should work.

Intel MKL SpareBlas mm CSR one-based indexing not working

I am testing the functions of Intel MKL in a C test-program and I found that I just can't make the spareblas: mkl_scsrmm function CSR one-based indexing work. I am using CSR with the val, columns, pntrb and pntre variation. The original examples where placed in:
"...mkl\examples\examples_core_c\spblasc\source\cspblas_scsr.c"
This is the first code for zero-based indexing:
Example #1
#include <stdio.h>
#include "mkl_types.h"
#include "mkl_spblas.h"
int main() {
#define M 2
#define NNZ 4
MKL_INT m = M, nnz = NNZ;
float values[NNZ] = {2.0,4.0,4.0,2.0};
MKL_INT columns[NNZ] = {1,2,1,2};
MKL_INT rowIndex[M+1] = {1,3,5};
#define N 2
MKL_INT n = N;
float b[M][N] = {2.0, 1.0, 5.0, 2.0};
float c[M][N] = {0.0, 0.0, 0.0, 0.0};
float alpha = 1.0, beta = 0.0;
char transa, uplo, nonunit;
char matdescra[6];
MKL_INT i, j, is;
transa = 'N';
matdescra[0] = 'S';
matdescra[1] = 'L';
matdescra[2] = 'N';
matdescra[3] = 'F';
mkl_scsrmm(&transa, &m, &n, &m, &alpha, matdescra, values, columns, rowIndex, &(rowIndex[1]), &(b[0][0]), &n, &beta, &(c[0][0]), &n);
printf(" \n");
printf(" OUTPUT DATA FOR MKL_SCSRMM\n");
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
printf("%7.1f", c[i][j]);
};
printf("\n");
};
return 0;
}
The results I get are this:
Zero-based indexing(the right one):
24.0 10.0
18.0 8.0
One-based indexing:
8.0 10.0
18.0 24.0
Though it seems like it only changes the diagonal elements position, with 3x3 matrix the solution its completly different from the right one. I suspected that it might be something with the input format of the matrix b. I think that there's lack of clarity on the description of array b for the function mkl_scsrmm placed in the MKL reference manual. Thus I changed b format, in this example and it worked (I placed elements position in this order: `{2.0, 5.0, 1.0, 2.0}) But I did the same for another 3x3 example I coded and it didn't work so I think it may be just a coincidence. I don't really know what to do with this problem, I would like to understand what happens here.
References:
CSR format
https://software.intel.com/en-us/node/471374
Spare Blas mkl_scsrmm function
https://software.intel.com/sites/products/documentation/doclib/iss/2013/mkl/mklman/hh_goto.htm#GUID-78C55D9B-86FF-4A9F-B5D5-D2F61B9314FC.htm
Spare Blas Interface Considerations
https://software.intel.com/sites/products/documentation/doclib/iss/2013/mkl/mklman/hh_goto.htm#GUID-34C8DB79-0139-46E0-8B53-99F3BEE7B2D4.htm
And here is another example, the 3x3 one:
Example #2
// matrix A
//
// 2 4 3
// 4 2 1
// 3 1 6
//
// matrix B
//
// 2 1 3
// 4 5 6
// 7 8 9
//
// ZERO-BASED INDEXING
//
// a = {2 4 3 4 2 1 3 1 6}
// columns= {0 1 2 0 1 2 0 1 2}
// idexRow = {0 3 6 9}
//
// b = {2 1 3 4 5 6 7 8 9} (row order array)
//
// We print the array in row-major order
//
// ONE-BASED INDEXING
//
// a = {2 4 3 4 2 1 3 1 6}
// columns={1 2 3 1 2 3 1 2 3}
// indexRow = {0 3 6 9}
//
// b = {2 4 7 1 5 8 3 6 9} (column order array)
//
// We print the array in column-major order (because the resoult is in column major order, ie transposed)
//
//
//
#include <stdio.h>
#include "mkl_types.h"
#include "mkl_spblas.h"
int main()
{
#define M 3
#define NNZ 9
#define N 3
MKL_INT m = M, nnz = NNZ, n=N;
float a[NNZ] = {2.0,4.0,3.0,4.0,2.0,1.0,3.0,1.0,6.0};
MKL_INT columns[NNZ] = {0,1,2,0,1,2,0,1,2};
MKL_INT rowIndex[M+1] = {0,3,6,9};
float b[M][N] = {2.0, 1.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0};
float c[M][N] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
float alpha = 1.0, beta = 0.0;
MKL_INT i, j;
char transa;
char matdescra[6];
float a1[NNZ] = {2.0,4.0,3.0,4.0,2.0,1.0,3.0,1.0,6.0};
MKL_INT columns1[NNZ] = {1,2,3,1,2,3,1,2,3};
MKL_INT rowIndex1[M+1] = {1,4,7,10};
float b1[M][N] = {2.0, 4.0, 7.0, 1.0, 5.0, 8.0, 3.0, 6.0, 9.0};
float c1[M][N] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
//********************************
//ZERO-BASED INDEXING
//********************************
transa = 'n';
matdescra[0] = 's';
matdescra[1] = 'l';
matdescra[2] = 'n';
matdescra[3] = 'c';
mkl_scsrmm(&transa, &m, &n, &m, &alpha, matdescra, a, columns, rowIndex, &(rowIndex[1]), &(b[0][0]), &n, &beta, &(c[0][0]), &n);
printf(" \n");
printf(" Right Solution: ZERO-BASED: C \n");
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++) {
printf("%7.1f", c[i][j]);
};
printf("\n");
};
printf(" \n");
printf(" ZERO-BASED: C' \n");
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
printf("%7.1f", c[j][i]);
};
printf("\n");
};
//********************************
//ONE-BASED INDEXING
//********************************
matdescra[3] = 'f';
mkl_scsrmm(&transa, &m, &n, &m, &alpha, matdescra, a1, columns1, rowIndex1, &(rowIndex1[1]), &(b1[0][0]), &n, &beta, &(c1[0][0]), &n);
printf(" \n");
printf(" ONE-BASED: C \n");
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
printf("%7.1f", c1[i][j]);
};
printf("\n");
};
printf(" \n");
printf(" ONE-BASED: C' \n");
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
printf("%7.1f", c1[j][i]);
};
printf("\n");
};
return 0;
}
I asked the same question at Intel's forum and I got some help there and get to the solution of the problem. The deal was that when calling the routine from C interface with zero-based indexing you can send the matrix stored in an array following row-major order (native C array storage), and when you call the routine with one-based indexing you have to store the matrix in column-major order. This changes the way the matrix B and C need to be stored, and the way the result will be stored. For the matrix A it only changes the indexing (from 0 to 1). From Intel's documentation you may think that the C interface accepts always the row-major ordering for both types of indexing.
Notice that it that in general, column-major ordering is not the same as storing the transposed matrix in row-major ordering (it is the same if matrices are square).

Resources