Graphviz 14.0.3~dev.20251111.0252
Loading...
Searching...
No Matches
matrix_market.c
Go to the documentation of this file.
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
11#include "matrix_market.h"
12#include "mmio.h"
13#include <sparse/SparseMatrix.h>
14#include <stdbool.h>
15#include <stdio.h>
16#include <util/alloc.h>
17
19 MM_typecode matcode;
20 double *val = NULL;
21 int *vali = NULL, m, n, nz;
22 void *vp = NULL;
24 int c;
25
26 if ((c = fgetc(f)) != '%') {
27 ungetc(c, f);
28 return NULL;
29 }
30 ungetc(c, f);
31 if (mm_read_banner(f, &matcode) != 0) {
32#ifdef DEBUG
33 printf("Could not process Matrix Market banner.\n");
34#endif
35 return NULL;
36 }
37
38 /* find out size of sparse matrix .... */
39 if (mm_read_mtx_crd_size(f, &m, &n, &nz) != 0) {
40 return NULL;
41 }
42 /* reseve memory for matrices */
43
44 int *I = gv_calloc(nz, sizeof(int));
45 int *J = gv_calloc(nz, sizeof(int));
46
47 const int type = matcode.type;
48 switch (type) {
50 val = gv_calloc(nz, sizeof(double));
51 for (int i = 0; i < nz; i++) {
52 int num = fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]);
53 if (num != 3) {
54 goto done;
55 }
56 I[i]--; /* adjust from 1-based to 0-based */
57 J[i]--;
58 }
59 if (matcode.shape == MS_SYMMETRIC) {
60 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
61 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
62 val = gv_recalloc(val, nz, 2 * nz, sizeof(double));
63 const int nzold = nz;
64 for (int i = 0; i < nzold; i++) {
65 if (I[i] != J[i]) {
66 I[nz] = J[i];
67 J[nz] = I[i];
68 val[nz++] = val[i];
69 }
70 }
71 } else if (matcode.shape == MS_SKEW) {
72 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
73 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
74 val = gv_recalloc(val, nz, 2 * nz, sizeof(double));
75 const int nzold = nz;
76 for (int i = 0; i < nzold; i++) {
77 if (I[i] == J[i]) { // skew symm should have no diag
78 goto done;
79 }
80 I[nz] = J[i];
81 J[nz] = I[i];
82 val[nz++] = -val[i];
83 }
84 } else if (matcode.shape == MS_HERMITIAN) {
85 goto done;
86 }
87 vp = val;
88 break;
90 vali = gv_calloc(nz, sizeof(int));
91 for (int i = 0; i < nz; i++) {
92 int num = fscanf(f, "%d %d %d\n", &I[i], &J[i], &vali[i]);
93 if (num != 3) {
94 goto done;
95 }
96 I[i]--; /* adjust from 1-based to 0-based */
97 J[i]--;
98 }
99 if (matcode.shape == MS_SYMMETRIC) {
100 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
101 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
102 vali = gv_recalloc(vali, nz, 2 * nz, sizeof(int));
103 const int nzold = nz;
104 for (int i = 0; i < nzold; i++) {
105 if (I[i] != J[i]) {
106 I[nz] = J[i];
107 J[nz] = I[i];
108 vali[nz++] = vali[i];
109 }
110 }
111 } else if (matcode.shape == MS_SKEW) {
112 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
113 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
114 vali = gv_recalloc(vali, nz, 2 * nz, sizeof(int));
115 const int nzold = nz;
116 for (int i = 0; i < nzold; i++) {
117 if (I[i] == J[i]) { // skew symm should have no diag
118 goto done;
119 }
120 I[nz] = J[i];
121 J[nz] = I[i];
122 vali[nz++] = -vali[i];
123 }
124 } else if (matcode.shape == MS_HERMITIAN) {
125 goto done;
126 }
127 vp = vali;
128 break;
130 for (int i = 0; i < nz; i++) {
131 int num = fscanf(f, "%d %d\n", &I[i], &J[i]);
132 if (num != 2) {
133 goto done;
134 }
135 I[i]--; /* adjust from 1-based to 0-based */
136 J[i]--;
137 }
138 if (matcode.shape == MS_SYMMETRIC || matcode.shape == MS_SKEW) {
139 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
140 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
141 const int nzold = nz;
142 for (int i = 0; i < nzold; i++) {
143 if (I[i] != J[i]) {
144 I[nz] = J[i];
145 J[nz++] = I[i];
146 }
147 }
148 } else if (matcode.shape == MS_HERMITIAN) {
149 goto done;
150 }
151 break;
152 case MATRIX_TYPE_COMPLEX: {
153 val = gv_calloc(2 * nz, sizeof(double));
154 double *const v = val;
155 for (int i = 0; i < nz; i++) {
156 int num =
157 fscanf(f, "%d %d %lg %lg\n", &I[i], &J[i], &v[2 * i], &v[2 * i + 1]);
158 if (num != 4) {
159 goto done;
160 }
161 I[i]--; /* adjust from 1-based to 0-based */
162 J[i]--;
163 }
164 if (matcode.shape == MS_SYMMETRIC) {
165 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
166 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
167 val = gv_recalloc(val, 2 * nz, 4 * nz, sizeof(double));
168 const int nzold = nz;
169 for (int i = 0; i < nzold; i++) {
170 if (I[i] != J[i]) {
171 I[nz] = J[i];
172 J[nz] = I[i];
173 val[2 * nz] = val[2 * i];
174 val[2 * nz + 1] = val[2 * i + 1];
175 nz++;
176 }
177 }
178 } else if (matcode.shape == MS_SKEW) {
179 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
180 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
181 val = gv_recalloc(val, 2 * nz, 4 * nz, sizeof(double));
182 const int nzold = nz;
183 for (int i = 0; i < nzold; i++) {
184 if (I[i] == J[i]) { // skew symm should have no diag
185 goto done;
186 }
187 I[nz] = J[i];
188 J[nz] = I[i];
189 val[2 * nz] = -val[2 * i];
190 val[2 * nz + 1] = -val[2 * i + 1];
191 nz++;
192 }
193 } else if (matcode.shape == MS_HERMITIAN) {
194 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
195 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
196 val = gv_recalloc(val, 2 * nz, 4 * nz, sizeof(double));
197 const int nzold = nz;
198 for (int i = 0; i < nzold; i++) {
199 if (I[i] != J[i]) {
200 I[nz] = J[i];
201 J[nz] = I[i];
202 val[2 * nz] = val[2 * i];
203 val[2 * nz + 1] = -val[2 * i + 1];
204 nz++;
205 }
206 }
207 }
208 vp = val;
209 break;
210 }
211 default:
212 goto done;
213 }
214
215 A = SparseMatrix_from_coordinate_arrays(nz, m, n, I, J, vp, type,
216 sizeof(double));
217done:
218 free(I);
219 free(J);
220 free(val);
221 free(vali);
222
223 if (A != NULL && matcode.shape == MS_SYMMETRIC) {
224 A->is_symmetric = true;
225 A->is_pattern_symmetric = true;
226 }
227
228 return A;
229}
SparseMatrix SparseMatrix_from_coordinate_arrays(int nz, int m, int n, int *irn, int *jcn, const void *val, int type, size_t sz)
@ MATRIX_TYPE_REAL
@ MATRIX_TYPE_PATTERN
@ MATRIX_TYPE_COMPLEX
@ MATRIX_TYPE_INTEGER
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
Definition alloc.h:73
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
expr procedure type
Definition exparse.y:208
#define A(n, t)
Definition expr.h:76
#define I
Definition expr.h:71
void free(void *)
node NULL
Definition grammar.y:181
SparseMatrix SparseMatrix_import_matrix_market(FILE *f)
import Matrix Market
int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz)
Definition mmio.c:92
int mm_read_banner(FILE *f, MM_typecode *matcode)
Definition mmio.c:28
Matrix Market I/O API
@ MS_SYMMETRIC
Definition mmio.h:31
@ MS_SKEW
Definition mmio.h:31
@ MS_HERMITIAN
Definition mmio.h:31
matrix_shape_t shape
Definition mmio.h:35
int type
one of the MATRIX_TYPE_* values from lib/sparse
Definition mmio.h:34