C: Finding maximum average of a 2 dimensional array - c

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

Related

C Programm with with duplicate values in a three-dimensional array

I have written a C program in which I output the lowest and highest temperature with day of the week and time in the lower function. However, sometimes values are duplicated. How can I implement this in my function so that both times are displayed?
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <limits.h>
double week_statistics(double array[52][7][24], int kalenderwoche, int j, int i, int k, int daymin, int hourmin, int daymax, int hourmax){
double min = array[0][0][0];
for(j = 0; j < 7; j++){
for(k = 0; k < 24; k++){
if(array[i][j][k] < min){
min = array[i][j][k];
daymin = j + 1;
hourmin = k + 1;
}}}
printf("Die niedrigste Temperatur war %lf° in der %d. Kalenderwoche am %d. Wochentag um %d Uhr.\n", min, kalenderwoche, daymin, hourmin);
double max = array[0][0][0];
for(i = 0; i < 52; i++){
for(j = 0; j < 7; j++){
for(k = 0; k < 24; k++){
if(array[i][j][k] > max){
max = array[i][j][k];
daymax = j + 1;
hourmax = k + 1;
}}}}
printf("Die höchste Temperatur war %lf° in der %d. Kalenderwoche am %d. Wochentag um %d Uhr.\n", max, kalenderwoche, daymax, hourmax);
}
int main(){
double array[52][7][24] = {{
{9.6, 9.4, 9.3, 9.1, 7.9, 7.7, 7.3, 7.2, 8.8, 9.3, 9.7, 9.4, 10.2, 9.7, 9.9, 9.5, 9.2, 9.3, 9.2, 7.1, 6.1, 5.9, 5.6, 5.2},
{4.9, 4.6, 4.6, 4.1, 3.5, 3.1, 2.6, 2.6, 3.5, 5.1, 6.2, 8.3, 9.0, 9.3, 9.1, 8.0, 6.8, 6.4, 5.4, 5.2, 4.8, 4.5, 5.0, 5.5},
{6.3, 6.8, 7.0, 7.2, 7.1, 7.2, 7.1, 7.4, 7.7, 8.2, 8.7, 9.1, 8.8, 8.7, 8.6, 8.4, 8.0, 7.9, 7.7, 7.6, 7.5, 7.3, 7.3, 7.2},
{7.1, 7.0, 6.9, 6.8, 6.7, 6.7, 6.7, 6.6, 6.7, 6.8, 6.9, 7.2, 7.5, 7.7, 8.1, 8.3, 8.0, 7.7, 8.1, 8.2, 7.7, 7.5, 7.7, 7.9},
{8.1, 8.0, 7.9, 7.8, 7.5, 7.2, 6.9, 7.2, 8.0, 8.4, 8.7, 9.0, 8.7, 8.9, 9.0, 7.8, 8.5, 8.1, 7.7, 7.7, 6.7, 7.0, 6.5, 7.1},
{6.4, 6.6, 6.3, 5.8, 5.0, 4.9, 4.7, 4.6, 4.9, 5.3, 6.1, 5.5, 5.3, 5.7, 5.8, 6.5, 6.6, 5.8, 5.8, 7.1, 7.0, 7.0, 6.3, 5.8},
{4.4, 4.0, 3.8, 3.8, 4.2, 4.2, 4.3, 3.8, 4.4, 5.2, 5.7, 5.9, 6.1, 6.7, 6.3, 5.9, 5.5, 5.1, 5.0, 5.0, 5.2, 5.7, 7.2, 7.7}
}};
int kalenderwoche = 45;
int i, j,k;
int daymin,daymax = 1;
int hourmin,hourmax = 1;
week_statistics(array, kalenderwoche, i, j ,k, daymin, hourmin, daymax, hourmax); //c)
}
In C programming for storing the values that you don't have their count without using any third party libraries, you have two main approaches. One way is to create an very large array and store your data into it, by using this approach you must have an upper bound for your number of inputs. Another way is using dynamic memory allocation. There are multiple ways for using dynamic memory allocation and one the simplest approach is using realloc and increasing a dynamically allocated memory one by one (this solution is simple for implementation and may not good enough for memory/time consumption).
First approach:
int daymin[100] = {0};
int dayminindex = 0;
...
daymin[dayminindex] = j + 1;
dayminindex++;
and the second approach is:
int *daymin = NULL;
int dayminlen = 0;
...
dayminlen++;
daymin = realloc(daymin, len * sizeof(int));
daymin[dayminlen - 1] = j + 1;
After applying the second approach in your code, we will have:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <limits.h>
double week_statistics(double array[52][7][24], int kalenderwoche){
int i, j, k;
int minlen = 0;
int *daymin = NULL;
int *hourmin = NULL;
double min = array[0][0][0];
for(i = 0; i < 52; i++){
for(j = 0; j < 7; j++){
for(k = 0; k < 24; k++){
if(array[i][j][k] < min) {
min = array[i][j][k];
minlen = 0;
free(daymin);
free(hourmin);
daymin = NULL;
hourmin = NULL;
}
// here we will add the first one
if(array[i][j][k] == min) {
minlen++;
daymin = realloc(daymin, minlen * sizeof(int));
daymin[minlen - 1] = j + 1;
hourmin = realloc(hourmin, minlen * sizeof(int));
hourmin[minlen - 1] = k + 1;
}
}
}
}
for (int i = 0; i < minlen; i++) {
printf("Die niedrigste Temperatur war %lf° in der %d. Kalenderwoche am %d. Wochentag um %d Uhr.\n", min, kalenderwoche, daymin[i], hourmin[i]);
}
int maxlen = 0;
int *daymax = NULL;
int *hourmax = NULL;
double max = array[0][0][0];
for(i = 0; i < 52; i++){
for(j = 0; j < 7; j++){
for(k = 0; k < 24; k++){
if(array[i][j][k] > max){
max = array[i][j][k];
maxlen = 0;
free(daymax);
free(hourmax);
daymax = NULL;
hourmax = NULL;
}
// here we will add the first one
if(array[i][j][k] == max){
maxlen++;
daymax = realloc(daymax, maxlen * sizeof(int));
daymax[maxlen - 1] = j + 1;
hourmax = realloc(hourmax, maxlen * sizeof(int));
hourmax[maxlen - 1] = k + 1;
}
}
}
}
for (int i = 0; i < maxlen; i++) {
printf("Die höchste Temperatur war %lf° in der %d. Kalenderwoche am %d. Wochentag um %d Uhr.\n", max, kalenderwoche, daymax[i], hourmax[i]);
}
}
int main(){
double array[52][7][24] = {
{
{9.6, 9.4, 9.3, 9.1, 7.9, 7.7, 7.3, 7.2, 8.8, 9.3, 9.7, 9.4, 10.2, 9.7, 9.9, 9.5, 9.2, 9.3, 9.2, 7.1, 6.1, 5.9, 5.6, 5.2},
{4.9, 4.6, 4.6, 4.1, 3.5, 3.1, 2.6, 2.6, 3.5, 5.1, 6.2, 8.3, 9.0, 9.3, 9.1, 8.0, 6.8, 6.4, 5.4, 5.2, 4.8, 4.5, 5.0, 5.5},
{6.3, 6.8, 7.0, 7.2, 7.1, 7.2, 7.1, 7.4, 7.7, 8.2, 8.7, 9.1, 8.8, 8.7, 8.6, 8.4, 8.0, 7.9, 7.7, 7.6, 7.5, 7.3, 7.3, 7.2},
{7.1, 7.0, 6.9, 6.8, 6.7, 6.7, 6.7, 6.6, 6.7, 6.8, 6.9, 7.2, 7.5, 7.7, 8.1, 8.3, 8.0, 7.7, 8.1, 8.2, 7.7, 7.5, 7.7, 7.9},
{8.1, 8.0, 7.9, 7.8, 7.5, 7.2, 6.9, 7.2, 8.0, 8.4, 8.7, 9.0, 8.7, 8.9, 9.0, 7.8, 8.5, 8.1, 7.7, 7.7, 6.7, 7.0, 6.5, 7.1},
{6.4, 6.6, 6.3, 5.8, 5.0, 4.9, 4.7, 4.6, 4.9, 5.3, 6.1, 5.5, 5.3, 5.7, 5.8, 6.5, 6.6, 5.8, 5.8, 7.1, 7.0, 7.0, 6.3, 5.8},
{4.4, 4.0, 3.8, 3.8, 4.2, 4.2, 4.3, 3.8, 4.4, 5.2, 5.7, 5.9, 6.1, 6.7, 6.3, 5.9, 5.5, 5.1, 5.0, 5.0, 5.2, 5.7, 7.2, 7.7}
}
};
int kalenderwoche = 45;
week_statistics(array, kalenderwoche);
}
There is a third approach that sometimes preferable when you have a stream of values and you just care about the statistics, not the individual values. (As you seem to have here.) You can take the data on-line in a single pass, only updating the values you care about.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct measure {
size_t count;
/* On-line numerically stable first-order, <Welford, 1962, Note>. */
double mean, ssdm;
struct { double min, max; } value;
struct { size_t min, max; } arg_hour, arg_day;
};
static void m_add(struct measure *const m, const double replica,
const size_t hour, const size_t day) {
const size_t n = ++m->count;
const double delta = replica - m->mean;
m->mean += delta / n;
m->ssdm += delta * (replica - m->mean);
if(n == 1 || replica < m->arg_hour.min) m->arg_hour.min = hour; /* argmin */
if(n == 1 || replica > m->arg_hour.max) m->arg_hour.max = hour; /* argmax */
if(n == 1 || replica < m->arg_day.min) m->arg_day.min = day; /* argmin */
if(n == 1 || replica > m->arg_day.max) m->arg_day.max = day; /* argmax */
if(n == 1 || replica < m->value.min) m->value.min = replica;
if(n == 1 || replica > m->value.max) m->value.max = replica;
}
static double m_mean(const struct measure *const m)
{ return m->count ? m->mean : 0. / 0.; }
static double m_sample_variance(const struct measure *const m)
{ return m->count > 1 ? m->ssdm / (m->count - 1) : 0. / 0.; }
static double m_stddev(const struct measure *const m)
{ return sqrt(m_sample_variance(m)); }
int main(void) {
double array[][7][24] = {
{
{ 9.6, 9.4, 9.3, 9.1, 7.9, 7.7, 7.3, 7.2, 8.8, 9.3, 9.7, 9.4,
10.2, 9.7, 9.9, 9.5, 9.2, 9.3, 9.2, 7.1, 6.1, 5.9, 5.6, 5.2 },
{ 4.9, 4.6, 4.6, 4.1, 3.5, 3.1, 2.6, 2.6, 3.5, 5.1, 6.2, 8.3, 9.0,
9.3, 9.1, 8.0, 6.8, 6.4, 5.4, 5.2, 4.8, 4.5, 5.0, 5.5 },
{ 6.3, 6.8, 7.0, 7.2, 7.1, 7.2, 7.1, 7.4, 7.7, 8.2, 8.7, 9.1, 8.8,
8.7, 8.6, 8.4, 8.0, 7.9, 7.7, 7.6, 7.5, 7.3, 7.3, 7.2 },
{ 7.1, 7.0, 6.9, 6.8, 6.7, 6.7, 6.7, 6.6, 6.7, 6.8, 6.9, 7.2, 7.5,
7.7, 8.1, 8.3, 8.0, 7.7, 8.1, 8.2, 7.7, 7.5, 7.7, 7.9},
{ 8.1, 8.0, 7.9, 7.8, 7.5, 7.2, 6.9, 7.2, 8.0, 8.4, 8.7, 9.0, 8.7,
8.9, 9.0, 7.8, 8.5, 8.1, 7.7, 7.7, 6.7, 7.0, 6.5, 7.1},
{ 6.4, 6.6, 6.3, 5.8, 5.0, 4.9, 4.7, 4.6, 4.9, 5.3, 6.1, 5.5, 5.3,
5.7, 5.8, 6.5, 6.6, 5.8, 5.8, 7.1, 7.0, 7.0, 6.3, 5.8},
{ 4.4, 4.0, 3.8, 3.8, 4.2, 4.2, 4.3, 3.8, 4.4, 5.2, 5.7, 5.9, 6.1,
6.7, 6.3, 5.9, 5.5, 5.1, 5.0, 5.0, 5.2, 5.7, 7.2, 7.7 }
}
};
const int kalenderwoche = 45;
size_t j, k;
struct measure m = { 0 };
for(j = 0; j < sizeof *array / sizeof **array; j++) {
for(k = 0; k < sizeof **array / sizeof ***array; k++) {
m_add(&m, array[0][j][k], k + 1, j + 1);
}
}
printf("Die niedrigste Temperatur war %lf° in der %d. Kalenderwoche am %zu. Wochentag um %zu Uhr.\n"
"Die höchste Temperatur war %lf° in der %d. Kalenderwoche am %zu. Wochentag um %zu Uhr.\n"
"Mean %f +/- %1.1f.\n",
m.value.min, kalenderwoche, m.arg_day.min, m.arg_hour.min,
m.value.max, kalenderwoche, m.arg_day.max, m.arg_hour.max,
m_mean(&m), m_stddev(&m));
}
I've also calculated the mean and standard-deviation using numerically-stable Welford's on-line algorithm using mean and ssdm, if you care about this.

Using pointers in division of two arrays

I need to store the results of two array's divisions in another array using pointers. But it displayed: arr3 = 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
How should I use a pointer to calculating that division part?
#include <stdio.h>
int main()
{
double arr1[10] = {10.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0};
double arr2[10] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,};
double arr3[10];
double *ptr=arr3;
int i=0;
for(i=0;i<10;i++)
{
*ptr = arr1[i]/arr2[i];
ptr++;
}
printf("arr3= ");
for(i=0;i<10;i++)
{
printf("%.2f ",*ptr);
ptr++;
}
return 0;
}
Just run at them as pointers as well. Also you needed to reset ptr to the head of the array after the first iteration.
double *ptr=arr3;
double *ptr1=arr1;
double *ptr2=arr2;
for(int i=0;i<10;i++)
{
*ptr = (*ptr1)/(*ptr2);
ptr++;ptr1++;ptr2++;
}
ptr=arr3;
for(i=0;i<10;i++)
{
printf("%.2f ",*ptr);
ptr++;
}
you need to reset your ptr to ptr=arr3; before your second loop, since what you are doing now is filling values untill 9 and displaying from 10 to 19 (adresses relative to arr3)

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.

Program to print and display identity matrix in 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.

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