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