CS211 Homework 3

This homework is meant to give you one last round of practice with C. It will involve a bit of pointer management and parsing some numbers from a file. The goal is to write a library that can create square matrices from the numbers in a file and can compute the dot product.

You will not be writing a main function for this assignment. Instead, you will complete the functions declared in matrix_lib.h.

You will be given a few testing programs and half of the library will be implemented in free_matrix.c. You will implement the other half of the functions in matrix_lib.c.

/*
 * The header file for 2D matrix operations.
 */

#include <stdio.h>

typedef struct Matrix Matrix;
struct Matrix {
    float* data;
    float** rows;
    size_t height;
    size_t width;
};

/*************************************
 * These functions are given to you.
 *************************************/

// Free the memory of a matrix.
void freeMatrix(Matrix);

// Create a string representing the matrix.
// Memory must be freed by the caller.
void printMatrix(Matrix);

// Add two matrices.
Matrix addMatrix(Matrix, Matrix);

/*************************************
 * These are the functions that you
 * must implement yourself.
 *************************************/

// Create a new matrix.
Matrix newMatrix(size_t height, size_t width);

// Read a matrix of unknown size from the FILE*
// You can re-use whatever number reading technique you developed in hw2
// You may also parse the file twice; once to count the numbers and a second time to populate the matrix.
Matrix readMatrix(FILE* datafile);

// Dot product of two matrices
Matrix dotProduct(Matrix, Matrix);

newMatrix

This function creates a new matrix of the given height and width. Differently from our example from class, you are being asked to allocate contiguous memory for the matrix, meaning that all memory for the floats stored in the array must be created in a single call to calloc.

// Create a new matrix.
Matrix newMatrix(size_t height, size_t width) {
    Matrix nm = {.data = NULL, .rows = NULL, .width = 0, .height = 0};
    if (0 == height * width) {
        return nm;
    }
    // First we allocate one pointer for the entire memory
    nm.data = calloc(width*height, sizeof(float));
    nm.height = height;
    nm.width = width;
    // TODO Now initialize rows.
    // It will be an array of pointers that point into nm.data.
    return nm;
}

The Matrix.rows values will still be pointers, but they will point to the proper locations within Matrix.data to access each row.

readMatrix

Files used will have all of their numbers on the same line, and you can assume that all matrices will be square (meaning that they have the same number of rows and columns). The simplest solution is to read the file twice, once to count the number of numbers and the second time to populate a newly created matrix.

The rewind function from stdio.h is useful for this. It will reset the state of a file back to the beginning: rewind(datafile);

Whatever method you used to parse numbers in homework 2 will work here.

Since you may want to use the sqrt function to find the width and height from the count of the numbers, the makefile will link to the math library.

dotProduct

The dot product of two matrices is a new matrix. Since all of our matrices will be square, the size of the new matrix is the same as either input. The values in each cell of the matrix come from the multiplication of the left matrix’s row down the right matrix’s column.

If the output’s name is product, then product[0][0] is the sum of left[0][i] * right[i][0] for each i in the size of the matrix (e.g. 0-3 for a 4 by 4 matrix).

If the multiplication won’t work because the matrices have different sizes, return 0-sized matrix, as in the addMatrix function.

Some examples:

make hw03_test1 will build a small test program that creates two 3x3 matrices and finds their sum and dot product.

$ make hw03_test1
gcc matrix_solution.c free_matrix.c test_matrix.c -lm -o hw03_test1
$ ./hw03_test1
Sum of matrix
1.000, 1.000, 1.000
1.000, 1.000, 1.000
1.000, 1.000, 1.000
And matrix
0.000, 0.000, 0.000
0.000, 1.000, 2.000
0.000, 2.000, 4.000
Is matrix
1.000, 1.000, 1.000
1.000, 2.000, 3.000
1.000, 3.000, 5.000
Dot product is matrix
0.000, 3.000, 6.000
0.000, 3.000, 6.000
0.000, 3.000, 6.000

Testing

A testing script will be provided shortly.

Submission

You should submit your matrix_lib.c file through Canvas.