Graphviz 14.1.2~dev.20251218.0900
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;
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 size_t nz;
40 if (mm_read_mtx_crd_size(f, &m, &n, &nz) != 0) {
41 return NULL;
42 }
43 /* reseve memory for matrices */
44
45 int *I = gv_calloc(nz, sizeof(int));
46 int *J = gv_calloc(nz, sizeof(int));
47
48 const int type = matcode.type;
49 switch (type) {
51 val = gv_calloc(nz, sizeof(double));
52 for (size_t i = 0; i < nz; i++) {
53 int num = fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]);
54 if (num != 3) {
55 goto done;
56 }
57 I[i]--; /* adjust from 1-based to 0-based */
58 J[i]--;
59 }
60 if (matcode.shape == MS_SYMMETRIC) {
61 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
62 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
63 val = gv_recalloc(val, nz, 2 * nz, sizeof(double));
64 const size_t nzold = nz;
65 for (size_t i = 0; i < nzold; i++) {
66 if (I[i] != J[i]) {
67 I[nz] = J[i];
68 J[nz] = I[i];
69 val[nz++] = val[i];
70 }
71 }
72 } else if (matcode.shape == MS_SKEW) {
73 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
74 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
75 val = gv_recalloc(val, nz, 2 * nz, sizeof(double));
76 const size_t nzold = nz;
77 for (size_t i = 0; i < nzold; i++) {
78 if (I[i] == J[i]) { // skew symm should have no diag
79 goto done;
80 }
81 I[nz] = J[i];
82 J[nz] = I[i];
83 val[nz++] = -val[i];
84 }
85 } else if (matcode.shape == MS_HERMITIAN) {
86 goto done;
87 }
88 vp = val;
89 break;
91 vali = gv_calloc(nz, sizeof(int));
92 for (size_t i = 0; i < nz; i++) {
93 int num = fscanf(f, "%d %d %d\n", &I[i], &J[i], &vali[i]);
94 if (num != 3) {
95 goto done;
96 }
97 I[i]--; /* adjust from 1-based to 0-based */
98 J[i]--;
99 }
100 if (matcode.shape == MS_SYMMETRIC) {
101 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
102 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
103 vali = gv_recalloc(vali, nz, 2 * nz, sizeof(int));
104 const size_t nzold = nz;
105 for (size_t i = 0; i < nzold; i++) {
106 if (I[i] != J[i]) {
107 I[nz] = J[i];
108 J[nz] = I[i];
109 vali[nz++] = vali[i];
110 }
111 }
112 } else if (matcode.shape == MS_SKEW) {
113 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
114 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
115 vali = gv_recalloc(vali, nz, 2 * nz, sizeof(int));
116 const size_t nzold = nz;
117 for (size_t i = 0; i < nzold; i++) {
118 if (I[i] == J[i]) { // skew symm should have no diag
119 goto done;
120 }
121 I[nz] = J[i];
122 J[nz] = I[i];
123 vali[nz++] = -vali[i];
124 }
125 } else if (matcode.shape == MS_HERMITIAN) {
126 goto done;
127 }
128 vp = vali;
129 break;
131 for (size_t i = 0; i < nz; i++) {
132 int num = fscanf(f, "%d %d\n", &I[i], &J[i]);
133 if (num != 2) {
134 goto done;
135 }
136 I[i]--; /* adjust from 1-based to 0-based */
137 J[i]--;
138 }
139 if (matcode.shape == MS_SYMMETRIC || matcode.shape == MS_SKEW) {
140 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
141 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
142 const size_t nzold = nz;
143 for (size_t i = 0; i < nzold; i++) {
144 if (I[i] != J[i]) {
145 I[nz] = J[i];
146 J[nz++] = I[i];
147 }
148 }
149 } else if (matcode.shape == MS_HERMITIAN) {
150 goto done;
151 }
152 break;
153 case MATRIX_TYPE_COMPLEX: {
154 val = gv_calloc(2 * nz, sizeof(double));
155 double *const v = val;
156 for (size_t i = 0; i < nz; i++) {
157 int num =
158 fscanf(f, "%d %d %lg %lg\n", &I[i], &J[i], &v[2 * i], &v[2 * i + 1]);
159 if (num != 4) {
160 goto done;
161 }
162 I[i]--; /* adjust from 1-based to 0-based */
163 J[i]--;
164 }
165 if (matcode.shape == MS_SYMMETRIC) {
166 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
167 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
168 val = gv_recalloc(val, 2 * nz, 4 * nz, sizeof(double));
169 const size_t nzold = nz;
170 for (size_t i = 0; i < nzold; i++) {
171 if (I[i] != J[i]) {
172 I[nz] = J[i];
173 J[nz] = I[i];
174 val[2 * nz] = val[2 * i];
175 val[2 * nz + 1] = val[2 * i + 1];
176 nz++;
177 }
178 }
179 } else if (matcode.shape == MS_SKEW) {
180 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
181 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
182 val = gv_recalloc(val, 2 * nz, 4 * nz, sizeof(double));
183 const size_t nzold = nz;
184 for (size_t i = 0; i < nzold; i++) {
185 if (I[i] == J[i]) { // skew symm should have no diag
186 goto done;
187 }
188 I[nz] = J[i];
189 J[nz] = I[i];
190 val[2 * nz] = -val[2 * i];
191 val[2 * nz + 1] = -val[2 * i + 1];
192 nz++;
193 }
194 } else if (matcode.shape == MS_HERMITIAN) {
195 I = gv_recalloc(I, nz, 2 * nz, sizeof(int));
196 J = gv_recalloc(J, nz, 2 * nz, sizeof(int));
197 val = gv_recalloc(val, 2 * nz, 4 * nz, sizeof(double));
198 const size_t nzold = nz;
199 for (size_t i = 0; i < nzold; i++) {
200 if (I[i] != J[i]) {
201 I[nz] = J[i];
202 J[nz] = I[i];
203 val[2 * nz] = val[2 * i];
204 val[2 * nz + 1] = -val[2 * i + 1];
205 nz++;
206 }
207 }
208 }
209 vp = val;
210 break;
211 }
212 default:
213 goto done;
214 }
215
216 A = SparseMatrix_from_coordinate_arrays(nz, m, n, I, J, vp, type,
217 sizeof(double));
218done:
219 free(I);
220 free(J);
221 free(val);
222 free(vali);
223
224 if (A != NULL && matcode.shape == MS_SYMMETRIC) {
225 A->is_symmetric = true;
226 A->is_pattern_symmetric = true;
227 }
228
229 return A;
230}
SparseMatrix SparseMatrix_from_coordinate_arrays(size_t 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, size_t *nz)
Definition mmio.c:93
int mm_read_banner(FILE *f, MM_typecode *matcode)
Definition mmio.c:29
Matrix Market I/O API
@ MS_SYMMETRIC
Definition mmio.h:32
@ MS_SKEW
Definition mmio.h:32
@ MS_HERMITIAN
Definition mmio.h:32
matrix_shape_t shape
Definition mmio.h:36
int type
one of the MATRIX_TYPE_* values from lib/sparse
Definition mmio.h:35