matrix_market.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #include <sparse/SparseMatrix.h>
  11. #include "mmio.h"
  12. #include "matrix_market.h"
  13. #include <stdbool.h>
  14. #include <util/alloc.h>
  15. SparseMatrix SparseMatrix_import_matrix_market(FILE * f)
  16. {
  17. int ret_code;
  18. MM_typecode matcode;
  19. double *val = NULL, *v;
  20. int *vali = NULL, i, m, n, *I = NULL, *J = NULL, nz;
  21. void *vp = NULL;
  22. SparseMatrix A = NULL;
  23. int nzold;
  24. int c;
  25. if ((c = fgetc(f)) != '%') {
  26. ungetc(c, f);
  27. return NULL;
  28. }
  29. ungetc(c, f);
  30. if (mm_read_banner(f, &matcode) != 0) {
  31. #ifdef DEBUG
  32. printf("Could not process Matrix Market banner.\n");
  33. #endif
  34. return NULL;
  35. }
  36. /* find out size of sparse matrix .... */
  37. if ((ret_code = mm_read_mtx_crd_size(f, &m, &n, &nz)) != 0) {
  38. return NULL;
  39. }
  40. /* reseve memory for matrices */
  41. I = gv_calloc(nz, sizeof(int));
  42. J = gv_calloc(nz, sizeof(int));
  43. const int type = matcode.type;
  44. switch (type) {
  45. case MATRIX_TYPE_REAL:
  46. val = gv_calloc(nz, sizeof(double));
  47. for (i = 0; i < nz; i++) {
  48. int num = fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]);
  49. if (num != 3) {
  50. goto done;
  51. }
  52. I[i]--; /* adjust from 1-based to 0-based */
  53. J[i]--;
  54. }
  55. if (matcode.shape == MS_SYMMETRIC) {
  56. I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
  57. J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
  58. val = gv_recalloc(val, nz, 2 * nz, sizeof(double));
  59. nzold = nz;
  60. for (i = 0; i < nzold; i++) {
  61. if (I[i] != J[i]) {
  62. I[nz] = J[i];
  63. J[nz] = I[i];
  64. val[nz++] = val[i];
  65. }
  66. }
  67. } else if (matcode.shape == MS_SKEW) {
  68. I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
  69. J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
  70. val = gv_recalloc(val, nz, 2 * nz, sizeof(double));
  71. nzold = nz;
  72. for (i = 0; i < nzold; i++) {
  73. if (I[i] == J[i]) { // skew symm should have no diag
  74. goto done;
  75. }
  76. I[nz] = J[i];
  77. J[nz] = I[i];
  78. val[nz++] = -val[i];
  79. }
  80. } else if (matcode.shape == MS_HERMITIAN) {
  81. goto done;
  82. }
  83. vp = val;
  84. break;
  85. case MATRIX_TYPE_INTEGER:
  86. vali = gv_calloc(nz, sizeof(int));
  87. for (i = 0; i < nz; i++) {
  88. int num = fscanf(f, "%d %d %d\n", &I[i], &J[i], &vali[i]);
  89. if (num != 3) {
  90. goto done;
  91. }
  92. I[i]--; /* adjust from 1-based to 0-based */
  93. J[i]--;
  94. }
  95. if (matcode.shape == MS_SYMMETRIC) {
  96. I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
  97. J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
  98. vali = gv_recalloc(vali, nz, 2 * nz, sizeof(int));
  99. nzold = nz;
  100. for (i = 0; i < nzold; i++) {
  101. if (I[i] != J[i]) {
  102. I[nz] = J[i];
  103. J[nz] = I[i];
  104. vali[nz++] = vali[i];
  105. }
  106. }
  107. } else if (matcode.shape == MS_SKEW) {
  108. I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
  109. J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
  110. vali = gv_recalloc(vali, nz, 2 * nz, sizeof(int));
  111. nzold = nz;
  112. for (i = 0; i < nzold; i++) {
  113. if (I[i] == J[i]) { // skew symm should have no diag
  114. goto done;
  115. }
  116. I[nz] = J[i];
  117. J[nz] = I[i];
  118. vali[nz++] = -vali[i];
  119. }
  120. } else if (matcode.shape == MS_HERMITIAN) {
  121. goto done;
  122. }
  123. vp = vali;
  124. break;
  125. case MATRIX_TYPE_PATTERN:
  126. for (i = 0; i < nz; i++) {
  127. int num = fscanf(f, "%d %d\n", &I[i], &J[i]);
  128. if (num != 2) {
  129. goto done;
  130. }
  131. I[i]--; /* adjust from 1-based to 0-based */
  132. J[i]--;
  133. }
  134. if (matcode.shape == MS_SYMMETRIC || matcode.shape == MS_SKEW) {
  135. I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
  136. J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
  137. nzold = nz;
  138. for (i = 0; i < nzold; i++) {
  139. if (I[i] != J[i]) {
  140. I[nz] = J[i];
  141. J[nz++] = I[i];
  142. }
  143. }
  144. } else if (matcode.shape == MS_HERMITIAN) {
  145. goto done;
  146. }
  147. break;
  148. case MATRIX_TYPE_COMPLEX:
  149. val = gv_calloc(2 * nz, sizeof(double));
  150. v = val;
  151. for (i = 0; i < nz; i++) {
  152. int num = fscanf(f, "%d %d %lg %lg\n", &I[i], &J[i], &v[0], &v[1]);
  153. if (num != 4) {
  154. goto done;
  155. }
  156. v += 2;
  157. I[i]--; /* adjust from 1-based to 0-based */
  158. J[i]--;
  159. }
  160. if (matcode.shape == MS_SYMMETRIC) {
  161. I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
  162. J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
  163. val = gv_recalloc(val, 2 * nz, 4 * nz, sizeof(double));
  164. nzold = nz;
  165. for (i = 0; i < nzold; i++) {
  166. if (I[i] != J[i]) {
  167. I[nz] = J[i];
  168. J[nz] = I[i];
  169. val[2 * nz] = val[2 * i];
  170. val[2 * nz + 1] = val[2 * i + 1];
  171. nz++;
  172. }
  173. }
  174. } else if (matcode.shape == MS_SKEW) {
  175. I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
  176. J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
  177. val = gv_recalloc(val, 2 * nz, 4 * nz, sizeof(double));
  178. nzold = nz;
  179. for (i = 0; i < nzold; i++) {
  180. if (I[i] == J[i]) { // skew symm should have no diag
  181. goto done;
  182. }
  183. I[nz] = J[i];
  184. J[nz] = I[i];
  185. val[2 * nz] = -val[2 * i];
  186. val[2 * nz + 1] = -val[2 * i + 1];
  187. nz++;
  188. }
  189. } else if (matcode.shape == MS_HERMITIAN) {
  190. I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
  191. J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
  192. val = gv_recalloc(val, 2 * nz, 4 * nz, sizeof(double));
  193. nzold = nz;
  194. for (i = 0; i < nzold; i++) {
  195. if (I[i] != J[i]) {
  196. I[nz] = J[i];
  197. J[nz] = I[i];
  198. val[2 * nz] = val[2 * i];
  199. val[2 * nz + 1] = -val[2 * i + 1];
  200. nz++;
  201. }
  202. }
  203. }
  204. vp = val;
  205. break;
  206. default:
  207. goto done;
  208. }
  209. A = SparseMatrix_from_coordinate_arrays(nz, m, n, I, J, vp,
  210. type, sizeof(double));
  211. done:
  212. free(I);
  213. free(J);
  214. free(val);
  215. if (A != NULL && matcode.shape == MS_SYMMETRIC) {
  216. A->is_symmetric = true;
  217. A->is_pattern_symmetric = true;
  218. }
  219. return A;
  220. }