Advertisement
Pweebs

Untitled

Oct 27th, 2019
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.07 KB | None | 0 0
  1. // Jevin Olano
  2. // jolano
  3. // CSE 101
  4. // October 24, 2019
  5. // Matrix.c - implementation file for Matrix ADT
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <assert.h>
  10. #include <math.h>
  11. #include "Matrix.h"
  12.  
  13. // Constructors & Destructors ---------------------------
  14.  
  15. // Returns a reference to a new nXn Matrix object in the zero state.
  16. Matrix newMatrix(int n) {
  17. Matrix M = malloc(sizeof(MatrixObj)); // matrix
  18. M->rows = calloc(n, sizeof(ListObj)); // rows
  19. for (int i = 0; i < n; i++) {
  20. M->rows[i] = newList(); // array elements
  21. }
  22. M->size = n;
  23. return M;
  24. }
  25.  
  26. // Frees heap memory associated with *pM, sets *pM to NULL.
  27. void freeMatrix(Matrix* pM) {
  28. Matrix M = *pM;
  29. makeZero(M);
  30. for (int i = 0; i < (M->size); i++) {
  31. freeList(&(M->rows[i])); // array elements
  32. }
  33. free(M->rows); // rows
  34. free(M); // matrix
  35. M = NULL;
  36. }
  37.  
  38. // Access Functions -------------------------------------
  39.  
  40. // size()
  41. // Return the size of square Matrix M.
  42. int size(Matrix M) {
  43. return M->size;
  44. }
  45.  
  46. // NNZ()
  47. // Return the number of non-zero elements in M.
  48. int NNZ(Matrix M) {
  49. int nonZeroCount = 0;
  50. for (int i = 0; i < (M->size); i++) {
  51. nonZeroCount += length(M->rows[i]);
  52. }
  53. return nonZeroCount;
  54. }
  55.  
  56. // doubleEquals()
  57. int doubleEquals(double a, double b) {
  58. return fabs(a - b) < 0.0000001 ? 1 : 0;
  59. }
  60.  
  61.  
  62. // equals()
  63. // Return true (1) if matrices A and B are equal, false (0) otherwise.
  64. int equals(Matrix A, Matrix B) {
  65. if (size(A) != size(B)) {
  66. return 0;
  67. }
  68. for (int i = 0; i < size(A); i++) {
  69. List rowA = A->rows[i];
  70. List rowB = B->rows[i];
  71. if (length(rowA) != length(rowB)) {
  72. return 0;
  73. }
  74. moveFront(rowA);
  75. moveFront(rowB);
  76. while (get(rowA) != NULL) {
  77. Entry entryA = (Entry) get(rowA);
  78. Entry entryB = (Entry) get(rowB);
  79. if (entryA->column != entryB->column || doubleEquals(entryA->value, entryB->value) == 0) {
  80. return 0;
  81. }
  82. moveNext(rowA);
  83. moveNext(rowB);
  84. }
  85. }
  86. return 1;
  87. }
  88.  
  89. // Manipulation Procedures ------------------------------
  90.  
  91. // makeZero()
  92. // Re-sets M to the zero Matrix.
  93. void makeZero(Matrix M) {
  94. for (int i = 0; i < (M->size); i++) {
  95. if (isEmpty(M->rows[i])) {
  96. continue;
  97. }
  98. moveFront(M->rows[i]);
  99. while (get(M->rows[i]) != NULL) {
  100. free(get(M->rows[i]));
  101. moveNext(M->rows[i]);
  102. }
  103. clear(M->rows[i]); // array elements
  104. }
  105. }
  106.  
  107. // newEntry()
  108. Entry newEntry(int column, double value) {
  109. Entry entry = malloc(sizeof(EntryObj));
  110. entry->column = column;
  111. entry->value = value;
  112. return entry;
  113. }
  114.  
  115. // appendToList()
  116. // helper method to add non-zero entries
  117. void appendToList(List list, Entry entry) {
  118. if (!doubleEquals(entry->value, 0)) {
  119. append(list, entry);
  120. } else {
  121. free(entry);
  122. }
  123. }
  124.  
  125. // changeEntry()
  126. // Changes the ith row, jth column of M to the value x.
  127. // Pre: 1<=i<=size(M), 1<=j<=size(M)
  128. void changeEntry(Matrix M, int i, int j, double x) {
  129. if (i < 1 || i > size(M)) {
  130. fprintf(stderr, "Error: row number is out of bounds\n");
  131. exit(1);
  132. }
  133. if (j < 1 || j > size(M)) {
  134. fprintf(stderr, "Error: column number is out of bounds\n");
  135. exit(1);
  136. }
  137. List row = M->rows[i-1];
  138. if (isEmpty(row)) {
  139. Entry entry = newEntry(j, x);
  140. appendToList(row, entry);
  141. } else {
  142. moveFront(row);
  143. int appendBool = 1;
  144. while (get(row) != NULL) {
  145. Entry entry = (Entry) get(row);
  146. if (entry->column == j) {
  147. if (doubleEquals(x, 0)) {
  148. delete(row);
  149. } else {
  150. entry->value = x;
  151. }
  152. appendBool = 0;
  153. break;
  154. } else if (entry->column < j) {
  155. moveNext(row);
  156. } else {
  157. if (!doubleEquals(x,0)) {
  158. insertBefore(row, newEntry(j, x));
  159. }
  160. appendBool = 0;
  161. break;
  162. }
  163. }
  164. if (appendBool == 1) {
  165. appendToList(row, newEntry(j, x));
  166. }
  167. }
  168. }
  169.  
  170. // Matrix Arithmetic Operations -------------------------
  171.  
  172. // copy()
  173. // Returns a reference to a new Matrix object having the same entries as A.
  174. Matrix copy(Matrix A) {
  175. Matrix B = newMatrix(size(A));
  176. for (int i = 0; i < size(A); i++) {
  177. List rowA = A->rows[i];
  178. List rowB = B->rows[i];
  179. if (isEmpty(rowA)) {
  180. continue;
  181. }
  182. moveFront(rowA);
  183. while (get(rowA) != NULL) {
  184. Entry entryA = (Entry) get(rowA);
  185. Entry entryB = newEntry(entryA->column, entryA->value);
  186. appendToList(rowB, entryB);
  187. moveNext(rowA);
  188. }
  189. }
  190. return B;
  191. }
  192.  
  193. // transpose()
  194. // Returns a reference to a new Matrix object representing the transpose of A.
  195. Matrix transpose(Matrix A) {
  196. Matrix B = newMatrix(size(A));
  197. for (int i = 0; i < size(A); i++) {
  198. List rowA = A->rows[i];
  199. if (isEmpty(rowA)) {
  200. continue;
  201. }
  202. moveFront(rowA);
  203. while (get(rowA) != NULL) {
  204. Entry entryA = (Entry) get(rowA);
  205. List rowB = B->rows[entryA->column - 1];
  206. Entry entryB = newEntry(i + 1, entryA->value);
  207. appendToList(rowB, entryB);
  208. moveNext(rowA);
  209. }
  210. }
  211. return B;
  212. }
  213.  
  214. // scalarMult()
  215. // Returns a reference to a new Matrix object representing xA.
  216. Matrix scalarMult(double x, Matrix A) {
  217. Matrix B = copy(A);
  218. for (int i = 0; i < size(A); i++) {
  219. List rowB = B->rows[i];
  220. moveFront(rowB);
  221. while (get(rowB) != NULL) {
  222. Entry entry = (Entry) get(rowB);
  223. entry->value *= x;
  224. moveNext(rowB);
  225. }
  226. }
  227. return B;
  228. }
  229.  
  230. // sum()
  231. // Returns a reference to a new Matrix object A+B
  232. // pre: size(A) == size(B)
  233. Matrix sum(Matrix A, Matrix B) {
  234. if (size(A) != size(B)) {
  235. fprintf(stderr, "Error: calling sum() on matrices of different size\n");
  236. exit(1);
  237. }
  238. Matrix C = newMatrix(size(A));
  239. for (int i = 0; i < size(A); i++) {
  240. double *pSums = calloc(size(A), sizeof(double));
  241.  
  242. List rowA = A->rows[i];
  243. moveFront(rowA);
  244. while (get(rowA) != NULL) {
  245. Entry entry = (Entry) get(rowA);
  246. pSums[entry->column - 1] = entry->value;
  247. moveNext(rowA);
  248. }
  249.  
  250. List rowB = B->rows[i];
  251. moveFront(rowB);
  252. while (get(rowB) != NULL) {
  253. Entry entry = (Entry) get(rowB);
  254. pSums[entry->column - 1] += entry->value;
  255. moveNext(rowB);
  256. }
  257.  
  258. List rowC = C->rows[i];
  259. for (int j = 0; j < size(A); j++) {
  260. if (!doubleEquals(pSums[j], 0)) {
  261. Entry sumEntry = newEntry(j + 1, pSums[j]);
  262. appendToList(rowC, sumEntry);
  263. }
  264. }
  265. free(pSums);
  266. }
  267. return C;
  268. }
  269.  
  270. // diff()
  271. // Returns a reference to a new Matrix object A-B
  272. // pre: size(A) == size(B)
  273. Matrix diff(Matrix A, Matrix B) {
  274. if (size(A) != size(B)) {
  275. fprintf(stderr, "Error: calling diff() on matrices of different size\n");
  276. exit(1);
  277. }
  278. Matrix C = newMatrix(size(A));
  279. for (int i = 0; i < size(A); i++) {
  280. double *pDiffs = calloc(size(A), sizeof(double));
  281.  
  282. List rowA = A->rows[i];
  283. moveFront(rowA);
  284. while (get(rowA) != NULL) {
  285. Entry entry = (Entry) get(rowA);
  286. pDiffs[entry->column - 1] = entry->value;
  287. moveNext(rowA);
  288. }
  289.  
  290. List rowB = B->rows[i];
  291. moveFront(rowB);
  292. while (get(rowB) != NULL) {
  293. Entry entry = (Entry) get(rowB);
  294. pDiffs[entry->column - 1] -= entry->value;
  295. moveNext(rowB);
  296. }
  297.  
  298. List rowC = C->rows[i];
  299. for (int j = 0; j < size(A); j++) {
  300. if (!doubleEquals(pDiffs[j], 0)) {
  301. Entry sumEntry = newEntry(j + 1, pDiffs[j]);
  302. appendToList(rowC, sumEntry);
  303. }
  304. }
  305. free(pDiffs);
  306. }
  307. return C;
  308. }
  309.  
  310. // vectorDot()
  311. // Computes the vector dot product of two matrix rows represented by Lists Q and P
  312. double vectorDot(List P, List Q, int size) {
  313. double *pP = calloc(size, sizeof(double));
  314. double *pQ = calloc(size, sizeof(double));
  315.  
  316. moveFront(P);
  317. while (get(P) != NULL) {
  318. Entry entry = (Entry) get(P);
  319. pP[entry->column - 1] = entry->value;
  320. moveNext(P);
  321. }
  322.  
  323. moveFront(Q);
  324. while (get(Q) != NULL) {
  325. Entry entry = (Entry) get(Q);;
  326. pQ[entry->column - 1] = entry->value;
  327. moveNext(Q);
  328. }
  329.  
  330. double product = 0.0;
  331.  
  332. for (int i = 0; i < size; i++) {
  333. product += pP[i] * pQ[i];;
  334. }
  335.  
  336. free(pP);
  337. free(pQ);
  338.  
  339. return product;
  340. }
  341.  
  342. // product()
  343. // Returns a reference to a new Matrix object AB
  344. // pre: size(A) == size(B)
  345. Matrix product(Matrix A, Matrix B) {
  346. if (size(A) != size(B)) {
  347. fprintf(stderr, "Error: calling product() on matrices of different size\n");
  348. exit(1);
  349. }
  350.  
  351. Matrix C = newMatrix(size(A));
  352. Matrix bTr = transpose(B);
  353.  
  354. for (int i = 0; i < size(A); i++) {
  355. for (int j = 0; j < size(bTr); j++) {
  356. Entry dotProduct = newEntry(j + 1, vectorDot(A->rows[i], bTr->rows[j], size(A)));
  357. appendToList(C->rows[i], dotProduct);
  358. }
  359. }
  360. freeMatrix(&bTr);
  361. return C;
  362. }
  363.  
  364. // printMatrix()
  365. // Prints a string representation of Matrix M to filestream out. Zero rows // are not printed. Each non-zero is represented as one line consisting
  366. // of the row number, followed by a colon, a space, then a space separated
  367. // list of pairs "(col, val)" giving the column numbers and non-zero values
  368. // in that row. The double val will be rounded to 1 decimal point.
  369. void printMatrix(FILE* out, Matrix M) {
  370. if (size(M) != 0) {
  371. for (int i = 0; i < size(M); i++) {
  372. if (isEmpty(M->rows[i])) {
  373. continue;
  374. }
  375. moveFront(M->rows[i]);
  376. fprintf(out, "%d:", i + 1);
  377. while (get(M->rows[i]) != NULL) {
  378. Entry entry = (Entry) get(M->rows[i]);
  379. fprintf(out, " (%d, %.1lf)", entry->column, entry->value);
  380. moveNext(M->rows[i]);
  381. }
  382. fprintf(out, "\n");
  383. }
  384. }
  385. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement