# Create A Matrix Calculator in C Assignment Solution.

## Instructions

Objective
Write a program to create a matrix calculator in C.

## Requirements and Specifications

Source Code

```LIST //----------------------------------------------------------------------------- // Nelson Pham, nppham // 2022 Winter CSE101 PA#4 // List.c // Implementation file for List ADT //----------------------------------------------------------------------------- #include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include "List.h" // structs -------------------------------------------------------------------- typedef struct NodeObj* Node; typedef struct NodeObj{   void* data;  Node prev;  Node next; }NodeObj; typedef struct ListObj{  Node front;  Node back;  Node cursorElmt;  int length;  int index; // index of cursor element }ListObj; // Constructors-Destructors --------------------------------------------------- // newNode() // Returns reference to new Node object. Initializes next and data fields. Node newNode(int* data){    Node N = malloc(sizeof(NodeObj));    N->data = data;    N->prev = NULL;    N->next = NULL;    return(N); } // freeNode() // Frees heap memory pointed to by *pN, sets *pN to NULL. void freeNode(Node* pN){    if( pN!=NULL && *pN!=NULL ){       free(*pN);       *pN = NULL;    } } List newList(void){ // Creates and returns a new empty List.  List L = malloc(sizeof(ListObj));  L->front = L->back = NULL;  L->cursorElmt = NULL;  L->length = 0;  L->index = -1; // index of cursor element  return(L); } void freeList(List* pL){  if (pL != NULL && *pL != NULL){   clear(*pL);   free(*pL);   *pL = NULL;  } } // Frees all heap memory associated with *pL, and sets  // *pL to NULL. // Access functions ----------------------------------------------------------- int length(List L){  if (L == NULL){   printf("List Error: calling length() on NULL List reference\n");   exit(EXIT_FAILURE);  }  return(L->length); } // Returns the number of elements in L. int index(List L){  if (L == NULL){   printf("List Error: calling index() on NULL List reference\n");   exit(EXIT_FAILURE);  }  if (length(L) <= 0){   return -1;  }  if (L->cursorElmt != NULL){   return L->index;  }  return -1; } // Returns index of cursor element if defined, -1 otherwise. void* front(List L){  if (L == NULL){   printf("List Error: calling front() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) <= 0){   printf("List Error: calling front() on empty List\n");   exit(EXIT_FAILURE);  }  return(L->front->data); } // Returns front element of L. Pre: length()>0 void* back(List L){  if (L == NULL){   printf("List Error: calling back() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) <= 0){   printf("List ErrorL calling back() on empty List\n");   exit(EXIT_FAILURE);  }  return(L->back->data); } // Returns back element of L. Pre: length()>0 void* get(List L){  if (L == NULL){   printf("List Error: calling get() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) <= 0){   printf("List Error: calling get() on empty List\n");   exit(EXIT_FAILURE);  }  if (index(L) < 0){   printf("List Error: invalid index on List\n");   exit(EXIT_FAILURE);  }  if (L->cursorElmt == NULL){   printf("List Error: calling get() on NULL cursor Element\n");   exit(EXIT_FAILURE);  }  return(L->cursorElmt->data); } // Returns cursor element of L. Pre: length()>0, index()>=0 int equalsList(List A, List B){  int eq = 0;  Node N = NULL;  Node M = NULL;  if (A==NULL || B==NULL){   printf("List Error: calling equals() on NULL list reference\n");   exit(EXIT_FAILURE);  }  eq = ( A->length == B ->length );  N = A->front;  M = B->front;  while(eq && N != NULL){   eq = (N->data == M->data);   N = N->next;   M = M->next;  }  return eq; } // Returns true iff Lists A and B are in same  // state, and returns false otherwise. // Manipulation procedures ---------------------------------------------------- void clear(List L){  if (L==NULL){   printf("List Error: calling clear() on NULL list reference\n");   exit(EXIT_FAILURE);  }  Node N = L->front;  Node M = NULL;  while(N != NULL){   M = N->next;   freeNode(&N);   N = M;  }  // List is back to empty state  L->front = NULL;  L->back = NULL;  L->cursorElmt = NULL;  L->index = -1;  L->length = 0; } // Resets L to its original empty state. void set(List L, void* x){  if (L==NULL){   printf("List Error: calling set() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) <= 0){   printf("List Error: calling set() on empty list\n");   exit(EXIT_FAILURE);  }  if (index(L) < 0){   printf("List Error: calling set() with invalid index list\n");   exit(EXIT_FAILURE);  }  L->cursorElmt->data = x; } // Overwrites the cursor element’s data with x.  // Pre: length()>0, index()>=0 void moveFront(List L){  if (L==NULL){   printf("List Error: calling moveFront() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) > 0){   L->cursorElmt = L->front;   L->index = 0;  } } // If L is non-empty, sets cursor under the front element,  // otherwise does nothing. void moveBack(List L){  if (L==NULL){   printf("List Error: calling moveBack() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) > 0){   L->cursorElmt = L->back;   L->index = length(L) - 1;  } } // If L is non-empty, sets cursor under the back element,  // otherwise does nothing. void movePrev(List L){  if (L==NULL){   printf("List Error: calling movePrev() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (L->cursorElmt == NULL){   return;  }  if (L->cursorElmt == L->front){   L->cursorElmt = NULL;   L->index = -1;  }  else{   L->cursorElmt = L->cursorElmt->prev;   L->index--;  } } // If cursor is defined and not at front, move cursor one  // step toward the front of L; if cursor is defined and at  // front, cursor becomes undefined; if cursor is undefined  // do nothing void moveNext(List L){  if (L==NULL){   printf("List Error: calling moveNext() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if(L->index >= 0){   L->cursorElmt = L->cursorElmt->next;   L->index++;   if(L->index == length(L)){    L->cursorElmt = NULL;     L->index = -1;   }  } } // If cursor is defined and not at back, move cursor one  // step toward the back of L; if cursor is defined and at  // back, cursor becomes undefined; if cursor is undefined  // do nothing void prepend(List L, void* x){  Node N = newNode(x);  if (L==NULL){   printf("List Error: calling prepend() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) <= 0){   L->front = N;   L->back = N;  }else{   N->next = L->front;   L->front->prev = N;   L->front = N;  }  L->index++; //increment index of cursor element since everything is being shifted to the right  L->length++; } // Insert new element into L. If L is non-empty,  // insertion takes place before front element. void append(List L, void* x){  Node N = newNode(x);  if (L==NULL){   printf("List Error: calling append() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) <= 0){   L->front = L->back = N;  }else{   N->prev = L->back;   L->back->next = N;   L->back = N;  }  L->length++; } // Insert new element into L. If L is non-empty,  // insertion takes place after back element. void insertBefore(List L, void* x){  //Node N = newNode(x);  if (L==NULL){   printf("List Error: calling insertBefore() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) <= 0){   printf("List Error: calling insertBefore() on empty list\n");   exit(EXIT_FAILURE);  }  if (index(L) < 0){   printf("List Error: calling insertBefore() on invalid index list\n");   exit(EXIT_FAILURE);  }  if(L->cursorElmt->prev == NULL){   prepend(L, x);   return;  }  Node N = newNode(x);  // Inserting before cursor  N->next = L->cursorElmt;  N->prev = L->cursorElmt->prev;  L->cursorElmt->prev->next = N;  L->cursorElmt->prev = N;  L->index++; // increment index of cursor element  L->length++; } // Insert new element before cursor.  // Pre: length()>0, index()>=0 void insertAfter(List L, void* x){  //Node N = newNode(x);  if (L==NULL){   printf("List Error: calling insertAfter() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) <= 0){   printf("List Error: calling insertBefore() on empty list\n");   exit(EXIT_FAILURE);  }  if (index(L) < 0){   printf("List Error: calling insertBefore() on invalid index list\n");   exit(EXIT_FAILURE);  }  if (L->cursorElmt->next == NULL){   append(L, x);   return;  }  Node N = newNode(x);  // Insert after cursor  N->next = L->cursorElmt->next;  L->cursorElmt->next->prev = N;  N->prev = L->cursorElmt;  L->cursorElmt->next = N;  L->length++; } // Insert new element after cursor.  // Pre: length()>0, index()>=0 void deleteFront(List L){  Node N = NULL;  if (L==NULL){   printf("List Error: calling deleteFront() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) <= 0){   printf("List Error: calling deleteFront() on empty list\n");   exit(EXIT_FAILURE);  }  N = L->front;  if (length(L) > 1){   L->front = L->front->next;   L->front->prev = NULL;  }else{   L->front = L->back = NULL;  }  L->length--;  freeNode(&N); } // Delete the front element. Pre: length()>0 void deleteBack(List L){  Node N = NULL;  if (L==NULL){   printf("List Error: calling deleteBack() on NULL list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) <= 0){   printf("List Error: calling deleteBack() on empty list\n");   exit(EXIT_FAILURE);  }  N = L->back;  if (length(L) > 1){   L->back = L->back->prev;   L->back->next = NULL;  }else{   L->back = L->front = NULL;  }  L->length--;  freeNode(&N); } // Delete the back element. Pre: length()>0 void delete(List L){  Node N = NULL;  if (L==NULL){   printf("List Error: calling delete() on Null list reference\n");   exit(EXIT_FAILURE);  }  if (length(L) <= 0){   printf("List Error: calling delete() on empty list\n");   exit(EXIT_FAILURE);  }  if (index(L) < 0){   printf("List Error: calling delete() in invalid index\n");   exit(EXIT_FAILURE);  }  N = L->cursorElmt;  L->cursorElmt = NULL;  L->length--;  N->prev->next = N->next;  N->next->prev = N->prev;  L->index = -1;  freeNode(&N); } // Delete cursor element, making cursor undefined.  // Pre: length()>0, index()>=0 // Other operations ----------------------------------------------------------- void printList(FILE* out, List L){  Node N = NULL;  if (L==NULL){   printf("List Error: calling printList() on NULL list reference\n");   exit(EXIT_FAILURE);  }  for(N=L->front; N != NULL; N = N->next){   fprintf(out, "%p ", N->data);  } } // Prints to the file pointed to by out, a  // string representation of L consisting  // of a space separated sequence of integers, // with front on left. List copyList(List L){  List A = newList();  Node N = NULL;  if (L==NULL){   printf("List Error: calling copyList() on NULL list reference\n");   exit(EXIT_FAILURE);  }  for(N = L->front; N != NULL; N = N->next){   append(A, N->data);  }  return A; } // Returns a new List representing the same integer  // sequence as L. The cursor in the new list is undefined, // regardless of the state of the cursor in L. The state // of L is unchanged. MATRIX // Nelson Pham, nppham // CSE101, PA#4 // Matrix.c // Matrix.c file to implement all the required functions in Matrix.h #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include "List.h" #include "Matrix.h" // Structs for Entry and Matrix typedef struct EntryObj {     int column;     double value; }EntryObj; typedef struct MatrixObj {     List *rows; // List of rows of matrix, pointer to a list     int size; } MatrixObj; // Creates newEntry with column value and actual value Entry newEntry(int col, double value) {     if (col < 0)     {         fprintf(stderr, "Error in newEntry function, col is less than 0\n");         return NULL;     }     Entry a = malloc(sizeof(EntryObj));     a->value = value;     a->column = col;     return a; } // Free the entry and set to NULL void freeEntry(Entry *e){     free(*e);     e = NULL; } // newMatrix() // Returns a reference to a new nXn Matrix object in the zero state. Matrix newMatrix(int n){     if (n < 0)     {         fprintf(stderr, "Error in newMatrix function, n is less than 0\n");         return NULL;     }     Matrix a = malloc(sizeof(MatrixObj));     a->rows = calloc(n, sizeof(List));     a->size = n;     for (int i = 0; i < n; i++)     {         a->rows[i] = newList();     }     return a; } // freeMatrix() // Frees heap memory associated with *pM, sets *pM to NULL. void freeMatrix(Matrix* pM){  int i;  for (i = 0; i<size(*pM); i++) {   List row = (*pM)->rows[i];   int len = length(row);   for (moveFront(row); index(row) != -1; moveNext(row)) {    Entry e = get(row);    freeEntry(&e);   }   freeList(&row);  }  free((*pM)->rows);  free(*pM); } // Access functions // size() // Return the size of square Matrix M. int size(Matrix M) {  return M->size; } // NNZ() // Return the number of non-zero elements in M. int NNZ(Matrix M){  int sum = 0, i;  for (i = 0; i<size(M); i++) {   List row = M->rows[i];   int len = length(row);   sum += len;  }  return sum; } // equals() // Return true (1) if matrices A and B are equal, false (0) otherwise. int equals(Matrix A, Matrix B){  int i;  int sizeA = size(A);  int sizeB = size(B);  if (sizeA != sizeB) {   return 0;  }  for (i = 0; i<sizeA; i++) {   int j;   List rowA = A->rows[i];   List rowB = B->rows[i];   moveFront(rowA);   moveFront(rowB);   while(1) {    int indexA = index(rowA);    int indexB = index(rowB);    if (indexA == -1) {     if (indexB == -1) {      break;     }     else {      return 0;     }    }    else {     if (indexB == -1) {      return 0;     }     else {      Entry eA = get(rowA);      Entry eB = get(rowB);      if (eA->column != eB->column) {       return 0;      }      else {       if (eA->value != eB->value) {        return 0;       }       moveNext(rowA);       moveNext(rowB);      }     }    }   }  }  return 1; } // Manipulation procedures // makeZero() // Re-sets M to the zero Matrix state. void makeZero(Matrix M){  int i;  for (i = 0; i<size(M); i++) {   List row = M->rows[i];   for(moveFront(row); index(row) != -1; moveNext(row)) {    Entry e = get(row);    freeEntry(&e);   }   clear(row);  } } // changeEntry() // Changes the ith row, jth column of M to the value x. // Pre: 1<=i<=size(M), 1<=j<=size(M) void changeEntry(Matrix M, int i, int j, double x){  List row = M->rows[i-1];  int len = length(row);  moveFront(row);  while (index(row) != -1) {   Entry e;   e = get(row);   if (e->column > j) {    if (x != 0.0) {     insertBefore(row, newEntry(j, x));    }    return;   }   if (e->column == j) {    if (x != 0.0) {     e->value = x;    }    else {     delete(row);    }    return;   }   moveNext(row);  }  if (x != 0.0) {   append(row, newEntry(j, x));  } } // Matrix Arithmetic operations // copy() // Returns a reference to a new Matrix object having the same entries as A. Matrix copy(Matrix A){  Matrix M = newMatrix(A->size);  int i;  for (i = 0; i<size(A); i++) {   List row = A->rows[i];   int len = length(row);   for (moveFront(row); index(row) != -1; moveNext(row)){    Entry e = get(row);    changeEntry(M, i+1, e->column, e->value);   }  }  return M; } // transpose() // Returns a reference to a new Matrix object representing the transpose // of A. Matrix transpose(Matrix A){  int i;  Matrix M = newMatrix(size(A));  for (i = 0; i<size(A); i++) {   List row = A->rows[i];   int len = length(row), j;   if (len == 0) {    continue;   }   moveFront(row);   while(index(row) != -1) {    Entry e = get(row);    changeEntry(M, e->column, i+1, e->value);    moveNext(row);   }  }  return M; } // scalarMult() // Returns a reference to a new Matrix object representing xA. Matrix scalarMult(double x, Matrix A){  int i;  Matrix M = newMatrix(size(A));  for (i = 0; i<size(A); i++) {   List row = A->rows[i];   int len = length(row), j;   if (len == 0) {    continue;   }   moveFront(row);   while(index(row) != -1) {    Entry e = get(row);    changeEntry(M, i+1, e->column, x * e->value);    moveNext(row);   }  }  return M; } // sum() // Returns a reference to a new Matrix object representing A+B. // pre: size(A)==size(B) Matrix sum(Matrix A, Matrix B){  int i;  int sizeA = size(A);  Matrix M = newMatrix(size(A));  Matrix Bcopy = copy(B);  for (i = 0; i<sizeA; i++) {   int j;   List rowA = A->rows[i];   List rowB = Bcopy->rows[i];   moveFront(rowA);   moveFront(rowB);   while(1) {    int indexA = index(rowA);    int indexB = index(rowB);    if (indexA == -1) {     if (indexB == -1) {      break;     }     else {      Entry eB = get(rowB);      changeEntry(M, i+1, eB->column, eB->value);      moveNext(rowB);     }    }    else {     if (indexB == -1) {      Entry eA = get(rowA);      changeEntry(M, i+1, eA->column, eA->value);      moveNext(rowA);     }     else {      Entry eA = get(rowA);      Entry eB = get(rowB);      if (eA->column < eB->column) {       changeEntry(M, i+1, eA->column, eA->value);       moveNext(rowA);      }      else if (eB->column < eA->column) {       changeEntry(M, i+1, eB->column, eB->value);       moveNext(rowB);      }      else {       changeEntry(M, i+1, eA->column, eA->value + eB->value);       moveNext(rowA);       moveNext(rowB);      }     }    }   }  }  freeMatrix(&Bcopy);  return M; } // diff() // Returns a reference to a new Matrix object representing A-B. // pre: size(A)==size(B) Matrix diff(Matrix A, Matrix B){  int i;  int sizeA = size(A);  Matrix M = newMatrix(size(A));  Matrix Bcopy = copy(B);  for (i = 0; i<sizeA; i++) {   int j;   List rowA = A->rows[i];   List rowB = Bcopy->rows[i];   moveFront(rowA);   moveFront(rowB);   while(1) {    int indexA = index(rowA);    int indexB = index(rowB);    if (indexA == -1) {     if (indexB == -1) {      break;     }     else {      Entry eB = get(rowB);      changeEntry(M, i+1, eB->column, -eB->value);      moveNext(rowB);     }    }    else {     if (indexB == -1) {      Entry eA = get(rowA);      changeEntry(M, i+1, eA->column, eA->value);      moveNext(rowA);     }     else {      Entry eA = get(rowA);      Entry eB = get(rowB);      if (eA->column < eB->column) {       changeEntry(M, i+1, eA->column, eA->value);       moveNext(rowA);      }      else if (eB->column < eA->column) {       changeEntry(M, i+1, eB->column, -eB->value);       moveNext(rowB);      }      else {       changeEntry(M, i+1, eA->column, eA->value - eB->value);       moveNext(rowA);       moveNext(rowB);      }     }    }   }  }  freeMatrix(&Bcopy);  return M; } // product() // Returns a reference to a new Matrix object representing AB // pre: size(A)==size(B) Matrix product(Matrix A, Matrix B){  int i;  int sizeA = size(A);  Matrix M = newMatrix(size(A));  Matrix Bt = transpose(B);  for (i = 0; i<sizeA; i++) {   int j;   List rowA = A->rows[i];   moveFront(rowA);   if (index(rowA) == -1) {    continue;   }   for (j = 0; j<sizeA; j++) {    List rowB = Bt->rows[j];    moveFront(rowB);    if (index(rowB) == -1) {     continue;    }    double sum = 0;    moveFront(rowA);    while(1) {     int indexA = index(rowA);     int indexB = index(rowB);     if (indexA == -1 || indexB == -1) {      break;     }     else {      Entry eA = get(rowA);      Entry eB = get(rowB);      if (eA->column < eB->column) {       moveNext(rowA);      }      else if (eB->column < eA->column) {       moveNext(rowB);      }      else {       sum += eA->value * eB->value;       moveNext(rowA);       moveNext(rowB);      }     }    }    changeEntry(M, i+1, j+1, sum);   }  }  freeMatrix(&Bt);  return M; } // printMatrix() // Prints a string representation of Matrix M to filestream out. Zero rows // are not printed. Each non-zero row is represented as one line consisting // of the row number, followed by a colon, a space, then a space separated // list of pairs "(col, val)" giving the column numbers and non-zero values // in that row. The double val will be rounded to 1 decimal point. void printMatrix(FILE* out, Matrix M){  int i;  for (i = 0; i<size(M); i++) {   List row = M->rows[i];   int len = length(row), j;   if (len == 0) {    continue;   }   fprintf(out, "%d: ", i+1);   for(moveBack(row); index(row)>=0; movePrev(row));   moveFront(row);   while(index(row) != -1) {    Entry e = get(row);    fprintf(out, "(%d, %.1f) ", e->column, e->value);    moveNext(row);   }   fprintf(out, "\n");  } } SPARSE #include <stdio.h> #include "Matrix.h" int main(int argc, char** argv) {   FILE *fin = fopen(argv[1], "r");   FILE *fout = fopen(argv[2], "w");  int n, a, b, k, i, j;  double x;  char buffer[256];  fscanf(fin, "%d", &n);  Matrix A = newMatrix(n), B = newMatrix(n), C, D, E, F, G, H, I, J;  fscanf(fin, "%d", &a);  fscanf(fin, "%d", &b);  fscanf(fin, "%[^\n]", buffer);  for (k = 0; k<a;k++) {   fscanf(fin, "%d", &i);   fscanf(fin, "%d", &j);   fscanf(fin, "%lf", &x);   fscanf(fin, "%[^\n]", buffer);   changeEntry(A, i, j, x);  }  for (k = 0; k<b;k++) {   fscanf(fin, "%d", &i);   fscanf(fin, "%d", &j);   fscanf(fin, "%lf", &x);   fscanf(fin, "%[^\n]", buffer);   changeEntry(B, i, j, x);  }  fprintf(fout, "A has %d non-zero entries:\n", NNZ(A));  printMatrix(fout, A);  fprintf(fout, "\n");  fprintf(fout, "B has %d non-zero entries:\n", NNZ(B));  printMatrix(fout, B);  fprintf(fout, "\n");  C = scalarMult(1.5, A);   fprintf(fout, "(1.5)*A =\n");   printMatrix(fout, C);   fprintf(fout, "\n");   D = sum(A, B);   fprintf(fout, "A+B =\n");   printMatrix(fout, D);   fprintf(fout, "\n");   E = sum(A, A);   fprintf(fout, "A+A =\n");   printMatrix(fout, E);   fprintf(fout, "\n");  F = diff(B, A);   fprintf(fout, "B-A =\n");   printMatrix(fout, F);   fprintf(fout, "\n");  G = diff(A, A);   fprintf(fout, "A-A =\n");   printMatrix(fout, G);   fprintf(fout, "\n");   H = transpose(A);   fprintf(fout, "Transpose(A) =\n");   printMatrix(fout, H);   fprintf(fout, "\n");   I = product(A, B);   fprintf(fout, "A*B =\n");   printMatrix(fout, I);   fprintf(fout, "\n");  J = product(B, B);   fprintf(fout, "B*B =\n");   printMatrix(fout, J);   fprintf(fout, "\n");  freeMatrix(&A);   freeMatrix(&B);   freeMatrix(&C);   freeMatrix(&D);   freeMatrix(&E);   freeMatrix(&F);   freeMatrix(&G);   freeMatrix(&H);   freeMatrix(&I);   freeMatrix(&J);  fclose(fin);  fclose(fout);   return 0; }```