All pastes #278131 Raw Edit

Anonymous

public text v1 · immutable
·published 2006-12-13 21:34 UTC
rendered paste body
/*
Shaun Guth
CIS15BG, Lee-Klawender
November 8, 2006

Mac OSX 10.4.8
gcc 4.0.1 (build 5363)

Lab 5 (Matrices/Structs)

This program tests some two-dimensional array functions
*/

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



#define MAX_DIMENSION 8 
#define MIN_DIMENSION 2
#define MAX_DOUBLE 100.0


// define our 2-dimensional array struct
typedef struct {
	double** data;
	int rows;
	int cols;
} MATRIX;



// testing framework
void get_dimensions (int* x, int* y);
MATRIX* init_matrix (MATRIX* m, int x, int y);
   void free_matrix (MATRIX* m);
MATRIX* fill_matrix (MATRIX* m);

// matrix operations
void add_matrices (MATRIX* m1, MATRIX* m2, MATRIX* r);
void invert_matrix (MATRIX* m);
void multiply_matrices (MATRIX* m1, MATRIX* m2, MATRIX* r);

// output
void print_matrix (char* label, MATRIX* m);



/*-------------------------------------------------------------------------*/


// program entry point
int main (void) {
	MATRIX matrix1, matrix2, matrix3; // matrices
    int dx,dy; // actual dimensions generated


    // seed random number generator
    //srand(3);
    srand( (unsigned)time(NULL) );

    // set the initial dimensions for this run
    get_dimensions(&dx, &dy);


	// initialize the first matrix
	if (NULL == init_matrix(&matrix1, dx, dy)) {
		printf("Error allocating memory for matrix1, exiting!\n");
		return 1;
	}

    // fill the first matrix with random numbers
    fill_matrix(&matrix1);


	// initialize the second matrix
	if (NULL == init_matrix(&matrix2, dx, dy)) {
		printf("Error allocating memory for matrix2, exiting!\n");
	}

	// fill the second matrix with random numbers
	fill_matrix(&matrix2);


	// print initial values to screen
    print_matrix("First Matrix:",  &matrix1);
    print_matrix("Second Matrix:", &matrix2);


    // add the first two matrices together, storing the sum in matrix3
    add_matrices(&matrix1, &matrix2, &matrix3);

	// print result
    print_matrix("Sum Matrix:", &matrix3);


    // invert the second matrix
    invert_matrix(&matrix2);

    // when printing, remember that the dimensions are now inverted
    print_matrix("Inverted Matrix:", &matrix2);


/*
    // multiply the first two matrices, storing product in third matrix
    multiply_matrices(&matrix1, &matrix2, &matrix3);

    // print the result of a multiplication
    print_matrix("Product Matrix:", &matrix3);
*/


    // successfully completed program
    return 0;
}


/*-------------------------------------------------------------------------*/


MATRIX* init_matrix (MATRIX* m, int x, int y) {
/*
PURPOSE: Allocate memory for MATRIX m
ACCEPTS: m (MATRIX pointer)
		 x (int) num of rows
		 y (int) num of cols
RETURNS: NULL on error, m otherwise
REMARKS:
*/
	int i; // loop index

	// invalid dimensions
	if (0 >= x || 0 >= y) {
		return NULL;
	}

	free_matrix(m);

	// allocate new array pointers
	m->data = (double**)calloc(x, sizeof(double*));
	if (NULL == m->data) {
		return NULL;
	}

	// allocate data storage
	for (i = 0; i < x; i++) {
		m->data[i] = (double*)calloc(y, sizeof(double));
		if (NULL == m->data[i]) {
			return NULL;
		}
	}

	// assign dimensions
	m->rows = x;
	m->cols = y;

	// allocated successfully
	return m;
}


/*-------------------------------------------------------------------------*/


void free_matrix (MATRIX* m) {
/*
PURPOSE: Frees memory for an allocated MATRIX m
ACCEPTS: m (MATRIX pointer)
RETURNS: (none)
REMARKS: Checks to see if there's anything to free first
*/
	int i; // loop index

	printf("Inside free_matrix()\n");
	if (NULL != m->data && 0 < m->rows && 0 < m->cols) {
		printf("m->data is NOT NULL, rows and cols are &gt; 0\n");
		for (i = 0; i < m->rows; i++) {
			if (NULL != m->data[i]) {
				printf("  freeing row %d\n", i);
				free(m->data[i]);
			}
		}
		printf("freeing m->data\n");
		free(m->data);
	}

	m->data = NULL;
}


/*-------------------------------------------------------------------------*/


void get_dimensions (int* x, int* y) {
/*
PURPOSE: Get 2 random values from the set [MAX_DIMENSION,MIN_DIMENSION]
ACCEPTS: x, y (int pointers) to store values in
RETURNS: (none)
REMARKS: Random number generator should be seeded with a call to srand()
*/
    *x = rand() % (MAX_DIMENSION-MIN_DIMENSION+1) + MIN_DIMENSION;
    *y = rand() % (MAX_DIMENSION-MIN_DIMENSION+1) + MIN_DIMENSION;
    return;
}


/*-------------------------------------------------------------------------*/


MATRIX* fill_matrix (MATRIX* m) {
/*
PURPOSE: Initialize a matrix of doubles with random values
ACCEPTS: m - MATRIX pointer
RETURNS: m
REMARKS: (none)
*/
    int ix,iy; // loop indices

    for (ix = 0; ix < m->rows; ix++) {
        for (iy = 0; iy < m->cols; iy++) {
            m->data[ix][iy] = (double)rand() / RAND_MAX * (MAX_DOUBLE+1);
        }
    }

    return m;
}


/*-------------------------------------------------------------------------*/


void add_matrices (MATRIX* m1, MATRIX* m2, MATRIX* r) {
/*
PURPOSE: Add two matrices together
ACCEPTS: m1, m2, r - MATRIX pointers
RETURNS: (none)
REMARKS: The 'r' parameter stores the sum of m1 + m2
*/
    int ix,iy; // loop indices

	// free the old result matrix
	free_matrix(r);

	// check that m1 and m2 are the same size
	if (m1->rows != m2->rows || m1->cols != m2->cols) {
		return;
	}
	
	// initialize new result matrix
	if (NULL == init_matrix(r, m1->rows, m1->cols)) {
		return;
	}
	
	// add matrices
    for (ix = 0; ix < m1->rows; ix++) {
        for (iy = 0; iy < m1->cols; iy++) {
            r->data[ix][iy] = m1->data[ix][iy] + m2->data[ix][iy];
        }
    }

    return;
}


/*-------------------------------------------------------------------------*/


void invert_matrix (MATRIX* m) {
/*
PURPOSE: Inverts the given matrix
ACCEPTS: m - MATRIX to be inverted
RETURNS: (none)
REMARKS: After inversion, m->rows and m->cols are swapped
*/
    int ix, iy; // loop indices
	MATRIX tmp;

	if (NULL == init_matrix(&tmp, m->cols, m->rows)) {
		return;
	}

	for (ix = 0; ix < m->rows; ix++) {
    	for (iy = 0; iy < m->cols; iy++) {
            tmp.data[iy][ix] = m->data[ix][iy];
        }
    }

	free_matrix(m);

	m->rows = tmp.rows;
	m->cols = tmp.cols;
	m->data = tmp.data;

    return;
}


/*-------------------------------------------------------------------------*/


void multiply_matrices (MATRIX* m1, MATRIX* m2, MATRIX* r) {
/*
PURPOSE: Multiplies two matrices together
ACCEPTS: m1, m2, r - MATRIX pointers
RETURNS: (none)
REMARKS: m2 should be inversely sized from m1
         ie, if m1 is 2x3, m2 should be 3x2
*/
    int i, j, k; // loop indices

	// free the old result matrix
	free_matrix(r);

	// check that m1 and m2 are inversely sized
	if (m1->cols != m2->rows || m1->rows != m2->cols) {
		return;
	}

	// initialize new result matrix (will be square)
	if (NULL == init_matrix(r, m1->rows, m1->rows)) {
		return;
	}

	// multiply
    for (i = 0; i < m1->rows; i++ ) {
        for (j = 0; j < m1->rows; j++) {
            r->data[i][j] = 0.0; // initialize result
            for (k = 0; k < m1->cols; k++) {
                r->data[i][j] += m1->data[i][k] * m2->data[k][j];
            }
        }
    }

    return;
}


/*-------------------------------------------------------------------------*/


void print_matrix (char* label, MATRIX* m) {
/*
PURPOSE: Prints a matrix to the screen
ACCEPTS: label - string to print out before the matrix
         m - MATRIX pointer
RETURNS: (none)
*/
    int ix,iy; // loop indices

    printf( "%s\n", label );

	if (NULL == m->data) {
		printf("Error with matrix.\n");
		return;
	}

    for (ix = 0; ix < m->rows; ix++) {
        for (iy = 0; iy < m->cols; iy++) {
            printf( "% 8.2f  ", m->data[ix][iy] );
        }
        printf( "\n" );
    }

    printf( "\n" );

    return;
}


/*-------------------------------------------------------------------------*/