简体   繁体   中英

Dynamic Memory Allocation for Matrix Multiplication

Currently I am working on a code that computes the following equation with two matrices, X and Y, to return the value of matrix W.

W = (XT * X)^-1 * XT * Y

Input Matrix train:

4
10
3.000000,1.000000,1180.000000,1955.000000,221900.000000
3.000000,2.250000,2570.000000,1951.000000,538000.000000
2.000000,1.000000,770.000000,1933.000000,180000.000000
4.000000,3.000000,1960.000000,1965.000000,604000.000000
3.000000,2.000000,1680.000000,1987.000000,510000.000000
4.000000,4.500000,5420.000000,2001.000000,1230000.000000
3.000000,2.250000,1715.000000,1995.000000,257500.000000
3.000000,1.500000,1060.000000,1963.000000,291850.000000
3.000000,1.000000,1780.000000,1960.000000,229500.000000
3.000000,2.500000,1890.000000,2003.000000,323000.000000

Input Matrix test:

3
3.000000,2.500000,3560.000000,1965.000000
2.000000,1.000000,1160.000000,1942.000000
3.000000,1.000000,1430.000000,1927.000000

Result Matrix:

716559
194430
323391

My code returns the proper values for the testcases with the exception of matrices over the size of 1000. I know this is because the size is not dynamically allocated, but I am not sure what the best approach to doing this in my code would be:

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[]){
        if(argc < 3){
                printf("error.");
                return 0;
        }
        FILE *fptrain = fopen(argv[1], "r");
        if(fptrain == NULL)
        {
                printf("error.");
                return 0;
        }
        int row, col, i, j;
        fscanf(fptrain, "%d", &col);
        col = col+1;
        fscanf(fptrain, "%d", &row);
        char ch;
        //creates the original X and Y matrix

        double trainX[row][col];
        double trainY[row][1];
        for(i=0; i<row; i++)
        {
                trainX[i][0] = 1.000000;
                for(j=1; j<col; j++)
                {
                        fscanf(fptrain, "%lf%c", &trainX[i][j], &ch);
                }
                        fscanf(fptrain, "%lf%c", &trainY[i][0], &ch);
        }
        //creates the X transposed matrix
        double trainXtrans[col][row];
        for(i=0; i<row; i++)
        {
                for(j=0; j<col; j++)
                {
                        trainXtrans[j][i] = trainX[i][j];
                }
        }
        //multiplies X and X transposed
        double trainXtemp[row][row];
        int s;
        double num=0;
        for(i=0; i<col; i++)
        {
                for(j=0; j<col; j++)
                {
                        for(s=0; s<row; s++)
                        {
                                num = num +  trainX[s][j]*trainXtrans[i][s];
                        }
                        trainXtemp[i][j] = num;
                        num = 0;
                }
        }
        //finds the identity matrix of X times X transposed
        double trainXinden[col][col*2];
        for(i=0; i<col; i++)
        {
                for(j=0; j<col; j++)
                {
                        trainXinden[i][j] = trainXtemp[i][j];
                }
                for(j=col; j<col*2; j++)
                {
                        if(j==i+col)
                        {
                                trainXinden[i][j] = 1.000000;
                        }
                        else{
                                trainXinden[i][j] = 0.000000;
                        }
                }
        }
        //finds the inverse of X times X transposed through Gauss Jordan Elimination
        int k;
        double divscalar;
        for(i=0; i<col; i++)
        {
                divscalar = trainXinden[i][i];
                for(j=0; j<col*2; j++)
                {
                        if(trainXinden[i][j] != 0)
                        {
                                trainXinden[i][j] = trainXinden[i][j]/divscalar;
                        }
                }
                for(k=0; k<col; k++)
                {
                        if(i!=k)
                        {
                                double subscalar = trainXinden[k][i];
                                for(j=0; j<col*2; j++)
                                {
                                        trainXinden[k][j] = trainXinden[k][j] - subscalar*trainXinden[i][j];
                                }
                        }
                }
        }
        double trainXinverse[row][row];       
        for(i=0; i<row; i++)          
        {        
                for(j=0; j<col; j++)              
                {        
                        trainXinverse[i][j] = trainXinden[i][j+col];            
                }        
        }        
        double trainXinvXt[col][row];
        for(i=0; i<col; i++)
        {
                for(j=0; j<row; j++)                  
                {                
                        for(s=0; s<col; s++)
                        {        
                                num = num + trainXinverse[i][s]*trainXtrans[s][j];
                        }
                                trainXinvXt[i][j] = num;
                                num = 0;
                }
        }
        //multiples (trainXinvXt) by Y
        double weight[row][1];
        for(i=0; i<col; i++)
        {
                for(s=0; s<row; s++)
                {
                        weight[i][0] +=  trainXinvXt[i][s]*trainY[s][0];
                }
        }

        FILE *fptest = fopen(argv[2], "r");
        if(fptest == NULL)
        {
                printf("error.");
                return 0;
        }
        int testrows;
        fscanf(fptest, "%d", &testrows);
        //creates the test file matrix

        double testM[testrows][col];
        for(i=0; i<testrows; i++)
        {
                testM[i][0] = 1.000000;
                for(j=1; j<col; j++)
                {
                        fscanf(fptest, "%lf%c", &testM[i][j], &ch);
                }
        }


        double prices[testrows][1];
        for(i=0; i<testrows; i++)
        {
                for(s=0; s<col; s++)
                {
                        num = num + testM[i][s]*weight[s][0];
                }
                prices[i][0] = num;
                num = 0;
        }

        for(i=0; i<testrows; i++)
        {
                printf("%0.0lf", prices[i][0]);
                printf("\n");
        }
return 0;
}

When I use malloc on each matrix, for some reason it appears that it is not allowing me to create the augmented matrix or perform my gauss-jordan reduction, which is ruining my final answer.

The best approach to allocate memory to a multi-dimensional array (taking eg of 2D array, since you are using matrix in your program):

int(*matrix)[col] = malloc (sizeof(int[row][col]));

If you want to write a function for it then:

void* allocMatrix (int row, int col)
{
    return malloc (sizeof(int[row][col]));
}

If you are not familiar with this approach of allocating memory dynamically to a multi-dimensional array then read this (very nicely explained by Lundin).

In your program, you are having the matrix of type double , so the allocMatrix() will be -

void* allocMatrix (int row, int col)
{
    return malloc (sizeof(double[row][col]));
}

and in main() , you need to make following changes to create matrix dynamically -

double (*trainX)[col] = allocMatrix (row, col);

Do same changes for other matrices also and make sure to free() the dynamically allocated memory to matrices at appropriate places in your program.

Just for the knowledge purpose, this practice of allocating memory to the multi-dimensional array has been followed commonly, though it's not the best.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM