Matrix Inversion C code problem

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • atemuoh1991
    New Member
    • Jul 2010
    • 5

    #1

    Matrix Inversion C code problem

    Code:
    #include <stdio.h>
    #include <math.h>
    #include <malloc.h>
    #include <stdlib.h>
    #include <time.h>
    
    
    struct SMatrix
    {
    	double** pValues;
    	int nR,nC;
    };
    
    #define MAX_COLUMN 30
    #define MAX_ROW 30
    
    void menu();
    int input_operation();
    void evaluate(int operation, float matrix[][MAX_ROW]);
    void addition(float matrix[][MAX_ROW]);
    void scalar_multiplication(float matrix[][MAX_ROW]);
    void matrix_multiplication(float matrix[][MAX_ROW]);
    void transpose(float matrix[][MAX_ROW]);
    struct SMatrix* inverse(float matrix[][MAX_ROW]);
    struct SMatrix* invert(float matrix[][MAX_ROW], int n);
    struct SMatrix* echelon(float m[(2*MAX_COLUMN)][MAX_ROW], int n);
    int find_max_row(float m[(2*MAX_COLUMN)][MAX_ROW], int cur_column, int start_row, int end);
    void reduce_echelon(float m[(2*MAX_COLUMN)][MAX_ROW], int index, int n);
    void reverse_echelon(float m[][MAX_ROW], int index, int n);
    void canonical_form(float m[][MAX_ROW], int index, int n);
    float get_product(float a[][MAX_ROW], float b[][MAX_ROW], int cur_col, int cur_row, int p);
    int get_size();
    float get_values();
    int input_scalar();
    void print_matrix(float m[][MAX_ROW], int column, int row);
    
    
    /*
     *	This function is used to obtain the inverse of a matrix nxn. If the matrix input is not a
     * square matrix, it prints out a message indicating that matrix is not invertible.
     *	Arguments:
     *		matrix:	an array where the values of the matrix are stored
     *		size: an array where the size of the matrix are temporarily stored when obtained from the user
     *	column, row: the size of the matrix
     *		i, cur_column, cur_row:	indices, counters
     *
     */
     
    struct SMatrix* inverse(struct SMatrix* A)
    {
    	int i,j;
    	float matrix[30][MAX_ROW];
    	for (i=0;i<3;i++)
    	{
    		for (j=0;j<3;j++)
    		{
    			matrix[i][j]=A->pValues[i][j];
    		}
    	}
    	int column=A->nR;
    	return invert(matrix, column);	
    }
    
    /*
     *	This function is a subfunction of inverse. It creates an augmented matrix M[A|I] used to
     * work with Gaussian Elimination to get the inverse of a matrix where A is the matrix and 
     * I is the identity matrix.
     * Arguments:
     *		matrix: 	an array where the values of the matrix input are stored
     *		m:			an array where the values of the augmented matrix are stored
     *		i:			the identity matrix
     *
     */
     
    struct SMatrix* invert(float matrix[][MAX_ROW], int n)
    {
    	float m[(2*MAX_COLUMN)][MAX_ROW];		/*augmented matrix*/
    	float i[MAX_COLUMN][MAX_ROW];				/*identity*/
    	int cur_row;
    	int cur_column;
    	
    	/*identity*/
    	for (cur_row = 0; cur_row < n; cur_row++)
    	{
    		for (cur_column = 0; cur_column < n; cur_column++)
    		{
    			if (cur_row == cur_column)
    			{
    				i[cur_column][cur_row] = 1;
    			}
    			else
    			{
    				i[cur_column][cur_row] = 0;
    			}
    		}
    	}
    	
    	/*augmented matrix, 1st half*/
    	for (cur_row = 0; cur_row < n; cur_row++)
    	{
    		for (cur_column = 0; cur_column < n; cur_column++)
    		{
    			m[cur_column][cur_row] = matrix[cur_column][cur_row];
    		}
    	}
    	/*augmented matrix, 2nd half*/
    	for (cur_row = 0; cur_row < n; cur_row++)
    	{
    		for (cur_column = n; cur_column < (2 * n); cur_column++)
    		{
    			m[cur_column][cur_row] = i[(cur_column - n)][cur_row];
    		}
    	}
    	
    	return echelon(m, n);
    }
    
    /*
     *	This is a subfunction of inverse where the augmented matrix is being reduced to echelon
     * form. If through the process of row operations a row zeros is obtained at the left side of
     * the augmented matrix or if any of the diagonal values is zero, it prints out an error 
     * message that the matrix has no inverse.
     *	Arguments:	
     *		m: the augmented matrix
     *		n: the size of the matrix being inverted
     *		inverse: an array to store the values of the inverted matrix
     *		temp: a temporary storage
     */
     
    struct SMatrix* echelon(float m[(2*MAX_COLUMN)][MAX_ROW], int n)
    {
    	int i;										/*counter*/
    	int cur_row;
    	int cur_column;
    	float inverse[MAX_COLUMN][MAX_ROW];
       float temp;  
    												 
    	
    	/*pivoting and swapping of rows*/
    	for (i = 0; i < (n-1); i++)
    	{
    		for (cur_row = i; cur_row < n; cur_row++)
    		{
    			int row_index_max = find_max_row(m, i, cur_row, n);
    	
    			for (cur_column = 0; cur_column < (2*n); cur_column++)
    			{
    				temp = m[cur_column][cur_row];
    				m[cur_column][cur_row] = m[cur_column][row_index_max];
    				m[cur_column][row_index_max] = temp;
    			}
    
    		}
    		reduce_echelon(m, i, n);
    		
    		if (m[i][i] == 0)
    		{
    			printf("\nMatrix has no inverse!\n\n");
    		}
    																																																								
    	}
    	
    	/*reverse row operations*/
    	for (i = (n-1); i > 0;i--)
    	{
    
    		reverse_echelon(m, i, n);
    
    	}
    	
    	/*reduces m to canonical form*/
    	for (i = 0; i < n; i++)
    	{
    		canonical_form(m, i, n);
    	}
    	
    	/*gets the inverse*/
    	for (cur_row = 0; cur_row < n; cur_row++)
    	{
    		for (cur_column = 0; cur_column < n; cur_column++)
    		{
    			inverse[cur_column][cur_row] = m[(cur_column + n)][cur_row];
    		}
    	}
    
    	int r,t;
    	struct SMatrix* Y;
    	Y->nC=3;
    	Y->nR=3;
    	for (r=0;r<3;r++)
    	{
    		for (t=0;t<3;t++)
    		{
    			Y->pValues[r][t]=inverse[r][t];
    		}
    	}
    		return (Y);
    
    }
    
    /*
     * This function is used to obtain the row which has the leading non-zero entry, an important
     * parameter in doing elementary row operations in obtaining the echelon form of an augmented
     * matrix.
     *	Arguments:
     * 	m: the augmented matrix
     *		cur_column, start_row, end: indices and counters
     * 	index_max_row: the index of the row which has the leading non-zero entry
     * Returns a value.
     *
     */
    
    int find_max_row(float m[(2*MAX_COLUMN)][MAX_ROW], int cur_column, int start_row, int end)
    {
    	int index_max_row = start_row;
    	int cur_row;
    	
    	for (cur_row = start_row; cur_row < end; cur_row++)
    	{
    		if (m[cur_column][cur_row] > m[cur_column][index_max_row])
    		{
    			index_max_row = cur_row;
    		}
    	}
    	return index_max_row;
    }
    
    /*
     *	This function is used to get the echelon form of the augmented matrix.
     * Arguments:
     *		m: the augmented matrix
     *		index: the current index of the values of the augmented matrix being reduced to echelon
     *		n: the size of the matrix nxn being inverted
     *		temp: temporary storage
     *		factor: the factor used to reduce the values of the matrix into echelon
     *
     */
     
    void reduce_echelon(float m[(2*MAX_COLUMN)][MAX_ROW], int index, int n)
    {
    	int cur_row;
    	int cur_column;
    	float temp;
    	float factor;
    	
    	for (cur_row = index; cur_row < (n-1); cur_row++)
    	{
    		factor = m[index][(cur_row + 1)]/m[index][index];
    		for (cur_column = index; cur_column < (n * 2); cur_column++)
    		{
    			temp = m[cur_column][(cur_row + 1)] - (factor * m[cur_column][index]);
    			m[cur_column][(cur_row + 1)] = temp;
    		}
    	}
    }
    
    /*
     * This function is used for the reverse elementary row operations.
     *
     */
     
    void reverse_echelon(float m[(2*MAX_COLUMN)][MAX_ROW], int index, int n)
    {
    	int cur_row;
    	int cur_column;
    	float temp;
    	float factor;
    		
    	for (cur_row = index; cur_row > 0; cur_row--)
    	{
    		factor = m[index][(cur_row - 1)]/m[index][index];
    		for (cur_column = index; cur_column < (2 * n); cur_column++)
    		{
    			temp = m[cur_column][(cur_row - 1)] - (factor * m[cur_column][index]);
    			m[cur_column][(cur_row -1)] = temp;
    		}
    	}	
    }
    
    /*
     * This function is used to obtain the canonical form of the reduced echolon form of the 
     * augmented matrix.
     *
     */
     
    void canonical_form(float m[(2*MAX_COLUMN)][MAX_ROW], int index, int n)
    {
    	int cur_column;
    	float temp;
    	float factor;
    	
    	factor = m[index][index];
    	
    	for (cur_column = index; cur_column < (n*2); cur_column++)
    	{
    		temp = m[cur_column][index]/factor; 
    		m[cur_column][index] = temp;
    	}
    }
    
    /*
     * This function is used to obtain the value of ijth entry of the product matrix.
     *	Arguments:
     *		a, b: arrays where the values of the matrices A and B are stored
     *		cur_col: the index of the current column value of the product
     *		p: equivalent to the row of A and column of B
     * 	sum: the value of the ijth entry of the product of matrices A and B
     *		product: temporary storage of the product of the ith row of A and jth column of B 
     * Returns a value.
     *
     */
     
    float get_product(float a[][MAX_ROW], float b[][MAX_ROW], int cur_col, int cur_row, int p)
    {
    	float sum = 0;
    	float product;
    	int i;
    	
    	for (i = 0; i < p; i++)
    	{
    		product = a[cur_col][i] * b[i][cur_row];
    		sum = sum + product;
    	}
    	return sum;
    }
    
    /*
     * This function is used to get the size of a matrix.
     * Arguments:
     * 	n:		a variable where to store the size input by the user
     * Returns a value.
     *
     */
     
    int get_size()
    {
    	int n;
    	
    	scanf("%d", &n);
    	return n;
    }
    
    /*
     * This function is used to get the values of a matrix. It scans values in fractional form 
     * (+|-)value_1/value_2 or in decimal form (+|-)value_1.value_2 where:
     *			+,- is the sign
     *			value_1 is the numerator (fractional form) and whole number (decimal form)
     *	   value_2 is the denominator (fractional form) and decimal value up to 2 digits (decimal form) 
     * Arguments:
     *		matrix:		an array to store the values of the matrix
     *		cur_column, cur_row: the indices where to store the value in the array
     *
     */
     
    float get_values()
    {
    
    	int n;
    	
    	scanf("%d", &n);
    	return n;
    /*	
    	if (dummy == SLASH)
    	{
    		value = (float)(value_1/value_2);
    	}	
    	else if (dummy == POINT)
    	{
    		value = (float)((value_1 * 100)+ value_2)/ 100;
    	}
    	
    	if (sign == POS)
    	{
    		value = value;
    	}
    	else if (sign == NEG)
    	{
    		value = -(value);
    	}
    */	
    //	matrix[cur_column][cur_row] = value;
    }
    
    /*
     * This function displays the resulting matrix derived from the operations.
     * Arguments:
     *		msg:		the message from which the matrix was derived
     *		matrix:	an array where the values of the matrix are stored
     *		column, row: the size of the matrix
     *
     */
     
    void print_matrix(float matrix[][MAX_ROW], int column, int row)
    {
    	int cur_row;
    	int cur_column;
    	
    	printf("Size: %d %d\n", column, row);
    	for (cur_row = 0; cur_row < row; cur_row++)
    	{
    		for (cur_column = 0; cur_column < column; cur_column++)
    		{
    			if (matrix[cur_column][cur_row] >= 0)
    			{
    				printf("+%f ", matrix[cur_column][cur_row]);
    			}
    			else
    			{
    				printf("%f ", matrix[cur_column][cur_row]);
    			}
    		}
    		printf("\n");
    	}
    }
    
    void PrintMatrix(struct SMatrix* pM) 
    {
    	int r,c;
    	for (r=0;r<pM->nR;r++)
    	{
    		for(c=0;c<pM->nC;c++)
    		{
    			printf("%5.5f\t\t", pM->pValues[r][c]);
    		}
    		printf("\n");
    	}
    }
    
    /*
     * This function obtains the scalar constant where the value can be any integer (+/-).
     * Arguments:
     * 	value:	where the integer is stored
     *		sign:		where the sign of the integer is stored
     * 	POS:		constant character equivalent to (+) sign
     *		NEG:		constant character equivalent to (-) sign
     * Returns a value.
     *
     */
    
    
    
    enum MFILLTYPE{MFT_NONE,  MFT_ZEORS, MFT_ONES,  MFT_RAND,  MFT_JEDENTITY};
    struct SMatrix* CreateMatrix(int nR,int nC,enum MFILLTYPE fillType)
    {
    	int r,c;
    	struct SMatrix* pRM;
    	pRM =(struct SMatrix*)malloc(sizeof(struct SMatrix));
    	pRM->nR = nR;
    	pRM->nC = nC;
    	//Allocate the matrix,  the matrix is an array of pointer to rows pointers
    	pRM->pValues = (double**)malloc(nR * sizeof(double*));
    	//Allocate the rows,  each row will point to all row elements for(r=0;r<nR;r++)
    	for (r=0;r<nR;r++)
    		pRM->pValues[r] = (double*)malloc(nC * sizeof(double));
    	if(fillType!=MFT_NONE)
    	{
    		for(r=0;r<nR;r++)
    			for(c=0;c<nC;c++)
    			{
    				switch(fillType) 
    				{
    					case MFT_ZEORS:
    						pRM->pValues[r][c] = 0; break; 
    					case MFT_ONES:
    						pRM->pValues[r][c] = 1; break;
    					case MFT_RAND:
    						pRM->pValues[r][c] = (rand()%100)/100.0; break;
    				
    					
    				}
    			}
    	}
    	return pRM;
    }
    
    void main ()
    {
    	struct SMatrix *A,*B;
    	A=CreateMatrix(3,3,MFT_RAND);
    	B=inverse(A);
    	PrintMatrix(B);
    
    }
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    What is your question exactly?

    It helps to state your problem and show only the code that applies to it rather than posting the whole thing and leaving it to us to figure out what might be your question.

    Comment

    • atemuoh1991
      New Member
      • Jul 2010
      • 5

      #3
      line 197, it refuses to return struct SMatrix Y

      Comment

      • atemuoh1991
        New Member
        • Jul 2010
        • 5

        #4
        here

        Comment

        • atemuoh1991
          New Member
          • Jul 2010
          • 5

          #5
          problem solved
          i forgot to use the CreateMatrix function :D

          Comment

          • weaknessforcats
            Recognized Expert Expert
            • Mar 2007
            • 9214

            #6
            This code in the echelon function:

            Code:
            struct SMatrix* Y; 
                Y->nC=3; 
                Y->nR=3;
            shows Y being defined. The address in Y is junk.

            Then junk is used to access nC. Result: crash. My compiler won't compile the code.

            You need a valid address in Y.

            BTW: There are mixtures of float and double in the code. A conversion of double to float doesn't work without possible loss of data. I suggest you use double throughout. Personlly, I would not use float unless there was a technical reason for me to do so that I could write down on paper.

            Comment

            • atemuoh1991
              New Member
              • Jul 2010
              • 5

              #7
              thnx i'll change them :)

              Comment

              Working...